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]
       +---+