Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的数组元素计数_C_Arrays_Alignment - Fatal编程技术网

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 阵列中没有“死区”;如果有填充,它将包含在结构的大小中。宏的大小返回结构的大小,包括所有填充。这对于静态定

我一直使用以下范例来迭代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
数组仍然是正确的。因此,声明:

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)
为1
long
需要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]`