转载前注明出处,欢迎转载分享
C Code
C Code
结构体:
大小:结构体的大小不是说结构体中的每个变量的数据类型之和就是结构体的大小,而是
按照内存对齐的方式来计算的。
1
2 3 4 5 6 7 8 9 |
struct { }; |
默认编译的时候结构体设定为4字节对齐,当然我们可以修改其对齐方法,代码如下:
1
|
#pragma |
那么一个空结构体占多大内存你知道么?
看如下代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 |
struct int { } |
gcc编译结果:
0
0, dd76fcd0
0, dd76fcd0
g++编译结果:
1
1, e906651f
1, e906651e
说到空结构体就得说说C语言的“灰色地带”,
C语言中空结构体占用的大小是0(在gcc中测试为0)。在C++中规定空结构体和空类所占内存大小为1。
C++语言标准规定“no object shall have the same address in memory as any other variable”,C++这样的规定原因如下:
1
2 3 |
struct D int |
这种指针相减运算在编译器中会等价于如下步骤:
1
2 3 |
struct D cnt |
如果允许C++对象大小为0,那么这里的运算将产生两个问题:
(1)
不能通过指针区分不同的数组对象;
(2)
sizeof D为0导致非法的除0操作。这样一来,编译器还需要用一些复杂的代码来处理这些异常情况信息。为了满足C++标准规定的不同对象不能有相同地址,C++编译器保证任何类型对象大小不能为0。
C++编译器会在空类或空结构体中增加一个虚设的字节,以确保不同的对象都具有不同的地址。
柔性数组:
结构体中最后一个元素允许是未知大小的数组,这个数组就是
柔性数组(soft array),也叫
伸缩性数组。但结构中的柔性数组前面必须
至少一个其他成员,如果是下面的情况则gcc编译错误:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct { };//error int { } |
但是g++编译可以通过,运行结果如下:
0
0, 1442db70
0, 1442db70
这和gcc编译空结构体的运行结果相似,接下来写一段简单的柔性数组的创建和运用,代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include #include #include #define typedef { } //create SoftArray { } void { } void { } int { } |
总结:也就是说对于空结构体而言,在gcc环境下编译结果显示该结构体所占空间大小为0,并且不同对象的地址相同。在g++环境下编译结果显示该结构体所占空间大小为1,并且不同对象的地址不同。如果结构体中仅为一个没有指定大小的数组时,用gcc编译会报错,而用g++编译时显示的结果是该结构体所占空间大小为0,并且不同对象的地址相同。
struct与union的区别:
struct中的每个域在内存中都独立分配空间
union只分配最大域的空间,所有域共享这块空间
代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
struct }; union }; int } |
输出分别为12和4
看到上述代码我们可以猜测出union的大小取决于其中一个类型的最大域。
来看如下代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include union { }; int { } |
按照上述猜测,这段代码的输出结果应该是9呀,怎么会是12呢?这跟
union的
内存对齐有关系。首先
找出联合的最大类型为int,然后
找出联合成员中占空间最大的是a[9],即占用9个字节,所以该联合大小至少为9,因为要满足与最大类型(这里是int)对齐的条件,所以要
整除最大类型即int(4字节),给9补齐3个字节,所以最终联合的大小为12个字节。