C中的数组元素计数
我一直使用以下范例来迭代C中静态定义的数组:C中的数组元素计数,c,arrays,alignment,C,Arrays,Alignment,我一直使用以下范例来迭代C中静态定义的数组: struct foo { ... }; struct foo array[10]; for (int i; i < sizeof(array) / sizeof(array[0]); i++) ... 编译器不应该因为对齐(LP64数据模型)而决定sizeof(struct foo)==7,而sizeof(array)==32 阵列中没有“死区”;如果有填充,它将包含在结构的大小中。宏的大小返回结构的大小,包括所有填充。这对于静态定
struct foo { ... };
struct foo array[10];
for (int i; i < sizeof(array) / sizeof(array[0]); i++)
...
编译器不应该因为对齐(LP64数据模型)而决定sizeof(struct foo)==7
,而sizeof(array)==32
阵列中没有“死区”;如果有填充,它将包含在结构的大小中。宏的大小返回结构的大小,包括所有填充。这对于静态定义的
struct
数组仍然是正确的。因此,声明:
sizeof(struct array) / sizeof(struct array[0])
将始终允许您遍历数组元素,而不管每个struct元素中有多少成员或成员的类型
填充/对齐对数组边界没有影响即使源代码中使用了指令,可能会导致打包更改(这也会影响对齐),从而导致数组中每个结构元素的sizeof值不同,数组元素的计数保持不变 …如果我的假设不总是成立的话,这是一个反例 需要注意的是:
sizeof
操作符在struct(或任何其他类型)数组上的工作方式不同,这些数组实际上是指针,在堆上动态创建。例如,如果您有:
typedef struct { ... }FOO;
FOO *foo;
...
foo = malloc(10*sizeof(FOO));
size_t size = sizeof(foo); //returns sizeof pointer, (4 bytes on 32 bit target)
//No matter how many, or what type members make up the struct
所以
将不再为您提供正确的数组元素计数。结构内部成员对齐对该结构的数组没有影响。因此,无论结构包含哪些成员或它们是如何对齐的,您所拥有的都可以保证工作 如果结构的成员之间有填充,那么结构数组的所有元素都是相同的
sizeof(数组)
总是可以被sizeof(数组[0])
平均整除
因此,计算数组大小的方法
size_t len = sizeof(array)/sizeof(array[0]);
只要数组
是一个数组,就可以保证适用于任何类型。关于sizeof
运算符的说明如下:
当应用于具有数组类型的操作数时,结果为
数组中的总字节数
以及:
示例2 sizeof运算符的另一个用途是计算数字
数组中元素的数目:
`sizeof array / sizeof array[0]`
所以数组的大小总是它的元素大小的倍数
在关于结构的同一段中:
应用于具有结构或并集类型的操作数时
结果是这样一个对象中的总字节数,包括
内部和尾部填充
编译器可以自由地在结构中成员之间的任意位置及其末尾插入填充,但第一个成员的偏移量必须始终为零 另一方面,数组必须始终是连续的,元素之间没有任何“间隙”。该标准规定: 数组类型描述连续分配的非空对象集 通常,大多数编译器会在结构的末尾插入一些填充,以确保在数组中连续排列时,第二个元素不会破坏某些成员的对齐要求。典型的规则是,结构的总尺寸必须扩展到一个尺寸,该尺寸可以被具有最大对齐要求的构件对齐均匀分割
在LP64型号中,
sizeof(long)
为8,sizeof(char)
为1long
需要8字节对齐,char
没有对齐要求。大小之和为9
,但编译器会将结构的大小扩展到16,以便16%8==0
。这样,相邻数组元素将从可被8
均匀整除的位置开始,因此第一个成员的对齐方式将被保留。如果我的假设为真,我将寻找规范引用;如果我的假设不总是成立,我将寻找反例。顺便说一句,是整数除法,它不会给你打错电话的。我错了吗?“编译器不应该决定sizeof(struct foo)==7
”不一定,可以有填充。您的范例是完整的,否则编译器将如何将索引解引用到该数组中?注意:您没有在给定的代码中初始化I
。同样来自标准:“当应用于具有结构或并集类型的操作数时,结果是这样一个对象中的总字节数,包括内部和尾部填充。”看起来你是对的,我可以使用gcc的\uuuuu属性\((压缩))
和例如\uu属性\((对齐(128)))调整结构大小
但无论我对数组做什么,它都是数组的常数倍。
size_t len = sizeof(array)/sizeof(array[0]);
`sizeof array / sizeof array[0]`