C编程(结构声明)
当我们声明说:C编程(结构声明),c,C,当我们声明说: int array[2]; array=“保存前32位的地址”,即它保存&数组[0]。 所以“数组”是一个指针。 但当我们声明一个结构时,例如: typedef struct x { int y; int array[2]; } 为什么这个结构的大小是16字节?既然“array”是指针,它不应该是8字节吗?我很困惑?首先array这里是一个数组,在结构中分配了空间来包含该数组的所有元素。它不是指向结构外部空间的指针。关于所有内容占用的空间大小,查看此处情况的
int array[2];
array=“保存前32位的地址”,即它保存&数组[0]
。
所以“数组”是一个指针。
但当我们声明一个结构时,例如:
typedef struct x
{
int y;
int array[2];
}
为什么这个结构的大小是16字节?既然“array”是指针,它不应该是8字节吗?我很困惑?首先
array
这里是一个数组,在结构中分配了空间来包含该数组的所有元素。它不是指向结构外部空间的指针。关于所有内容占用的空间大小,查看此处情况的最简单方法是在此处运行一些sizeof
检查:
#include <stdio.h>
typedef struct x
{
int y;
int array[2];
};
int main(void) {
struct x test1;
printf("sizeof(int) %zu \n", sizeof(int));
printf("sizeof(test1) %zu \n", sizeof(test1));
printf("sizeof(test1.array) %zu", sizeof(test1.array));
return 0;
}
#包括
类型定义结构x
{
int-y;
int数组[2];
};
内部主(空){
结构x测试1;
printf(“sizeof(int)%zu\n”,sizeof(int));
printf(“sizeof(test1)%zu\n”,sizeof(test1));
printf(“sizeof(test1.array)%zu”,sizeof(test1.array));
返回0;
}
在ideone上运行时,这里有4、12和8。
在其他系统上,我运行了这个程序,得到了类似的结果,这让我相信,在您的机器上,使用特定的编译器选项,一些填充已经添加到了您的结构中
如果sizeof(test1.y)+sizeof(test1.array)!=sizeof(test1)
然后添加了一些填充。添加诸如#pragma pack
(ms编译器)或uu属性((uu packed_uu))
(gcc)之类的内容可能会改变这一点
编译器添加填充的原因是,在特定系统上,在内存中具有这种特定对齐方式(16字节的倍数)的数据结构可能会在数据访问速度方面带来一些好处。关于这方面的更多信息,我建议看一看。数组具有指针的某些特征,但它本身不是指针。也就是说,你不能在其他地方指出这一点。它总是指向其分配的元素
因此,包含数组的
struct
不包含指针。在您的例子中,它包含两个int
s加上非数组int。显然,您的CPU是32位的,因此它包含12个字节的数据(三个4字节的int)。但是添加了一些结构填充,以使每个项落在8字节的边界上(为了CPU访问效率)。这使得它有16个字节长。有编译器选项“打包”结构,这样就不会发生填充。通常,在文件中的一行或编译器命令行选项上使用#pragma pack(0)
。这提供了一个关于打包对int和char的影响的概念
#include <stdio.h>
#pragma pack (push, 1)
typedef struct {
int a;
int b[2];
}TEST1;
typedef struct {
int a;
int b[2];
char c;
}TEST2;
#pragma pack(pop)
typedef struct {
int a;
int b[2];
}TEST3;
typedef struct {
int a;
int b[2];
char c;
}TEST4;
int main(){
printf(" ==== PAKED =====\t==== DEFAULT =====\n");
printf("sizeof(TEST1)=%d \tsizeof(TEST3)=%d\n",sizeof(TEST1),sizeof(TEST3));
printf("sizeof(TEST2)=%d \tsizeof(TEST4)=%d\n\n",sizeof(TEST2),sizeof(TEST4));
return 0;
}
当我们声明说:
int数组[2]代码>
array=“保存前32位的地址”,即保存&array[0]
没有。一点也不。当您声明一个2元素数组时,得到的结果如下所示:
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
与标识符arr
关联的对象是int
的2元素数组,而不是指针。在大多数情况下,表达式arr
将被转换(“衰减”)为“指向int
的指针”类型的表达式
struct
类型的实例如下所示:
+---+
y: | |
+---+
array: | | array[0]
+---+
| | array[1]
+---+
成员大小之和只有12个字节,因此在数组
之后必须有一些填充,以满足8字节或16字节的对齐限制 数组不是指针,尽管在某些情况下它可能会退化为指针,但在这里,整个数组存储在结构中。最可能的情况是,您正在为x64编译并且sizeof(int)==4
,因此您有12个有意义的字节和4个填充字节,总共16个字节。array
实际上是一个数组,而不仅仅是一个指针。这意味着2
元素的大小实际上是在x
struct.sizeof(struct x)的每个实例中分配的。定义为{int,{int,int}@允许milevyo(任意)填充。@milevyo,允许任意填充。C没有指定可以或应该使用多少填充。实际上,64位机器的C编译器可能更喜欢将结构填充到64位(8字节)的倍数,以便能够在64位边界上对齐它们。在这种情况下,如果int
是4个字节,那么给定的结构将需要填充到总共16个字节。
+---+
y: | |
+---+
array: | | array[0]
+---+
| | array[1]
+---+