C++内存结构体联合体所占内存

时间:2022-02-04 19:54:48

先明白下面几个事:

32位操作系统和VS32位编译器有区别么?待解答

32位操作系统中:
int 4字节
char 1字节
long 4字节
long long 8字节

64位操作系统中:
int 4字节
char 1字节
long 8字节(为啥验证是4呢,待解答)
long long 8字节

看struct

//64位操作系统
struct name1 {
char a;
int b;
long long c;
};//16
struct name2
{
char a;
long long b;
int c;
};//24
struct name3
{
char a;
int b;
int c;
};//12
cout << sizeof(name1) << " " << sizeof(name2) << " "<<sizeof(name3)<<endl;//输出结果如上面的注释

来一个union

typedef union1 { long  i;int k[5];char c; }DATA;
cout << sizeof(DATA) << endl;
//输出结果是20

先来解释一下为啥是20?
因为union里所有变量共有一块起始内存,所以要以最大的那个来作为占用内存的值来作为union占用的内存。上述中,int k[5]是占用5*4=20字节,所以是20。(注意这里是以4字节为单位)
但是还有一点点需要继续往下挖!

typedef union2 { long long i;int k[5];char c; }DATA;//如果是long long
cout << sizeof(DATA) << endl;
//输出结果是24

嘿嘿!想想这里为啥是24,而不是20了呢???
这是本文写的最重要的一点!
原因是:在union里,long long是8字节,而后面跟着的int k[5],是20字节,但是这个20字节是以[4][4][4][4][4]这样存的。前面有个[8]了,要以8字节为单位,int k[5]存储时,要成这样了,[[4][4]][[4][4]][[4][]],注意最后一个[4]后面需要补充一个4字节的。此时最大的还是int k[5],但是占用的内存是24字节。

再来一个struct

struct data {
int cat;DATA cow;double dog;
}too;
DATA max;
cout << sizeof(struct data) <<" "<< sizeof(max) << endl;

//如果DATA是20字节,即union1的,此时输出结果是:32(4+20+8)+20
//如果DATA是24字节,即union2的,此时输出结果是:40(8+24+8)+24
因为第二种是按照8字节对齐的。

再来一个小变化:

typedef union3 { long  i;int k[6];char c; }DATA;
cout << sizeof(DATA) << endl;

输出结果是:24

struct data {
int cat;DATA cow;double dog;
}too;
DATA max;
cout << sizeof(struct data) <<" "<< sizeof(max) << endl;

输出结果是:40(8+24+8)+24
好好想想是为啥?(因为double 是8字节,要按照double来对齐)

再来一个:

struct s1
{
int i:8;
int j:4;
int a:3;
double b;
};
cout << sizeof(s1) << endl;

输出结果是:16
首先要明白:int i:8是说i要占8bit的内存。因为最后一个是double,8字节,64bit,所以在struct是以8字节来对齐的,前面8+4+3=15bit,达不到8字节,但是要分配8字节。

struct s1
{
int i:16;
int j:31;
int a:2;
double b;
};
cout << sizeof(s1) << endl;

这个结果是24,这是因为内存是默认以一个4字节为一个对齐单位的。int i自己占用4字节,但是只用16bit,而int j是也是占用4字节,但是只用31bit,最后的a,不得不用4字节。但是要和最后的8字节对齐,所以前两个占用8字节,中间8字节,最后8字节,总共24.

struct s1
{
int i:16;
int j:30;
int a:2;
double b;
};
cout << sizeof(s1) << endl

这个输出结果就是16.(因为j和a可以拼成一个int)。