C中的数组元素计数

时间:2016-01-14 14:13:28

标签: c arrays alignment

我总是使用以下范例来迭代C中的静态定义数组:

struct foo { ... };
struct foo array[10];

for (int i; i < sizeof(array) / sizeof(array[0]); i++)
    ...

而且,到目前为止,每次都有效; - )

但令人惊讶的是,如果结构的长度实际上没有自然对齐,那么这不会破坏,例如:

struct foo { long a; char b; };

由于对齐(LP64数据模型),编译器是否应该决定sizeof(struct foo) == 7sizeof(array) == 32

5 个答案:

答案 0 :(得分:5)

由于C99 standard, section 6.5.3.4说明sizeof运算符:

  

当应用于具有数组类型的操作数时,结果为   数组中的总字节数。

  

示例2 sizeof运算符的另一个用途是计算数字   数组中的元素:

     `sizeof array / sizeof array[0]`

因此,数组的大小总是是它的元素大小的倍数。

关于结构的同一段:

  

当应用于具有结构或联合类型的操作数时,   result是这样一个对象的总字节数,包括   内部和尾部填充。

答案 1 :(得分:4)

没有

阵列中没有“死空间”;如果有填充,则//define the link element in a parent g var link = svg.selectAll("g.link") .data(json.links) .enter().append("g") .on("click", linkMouseClick) .on("mouseover", linkMouseover); //append a visible child line to parent g var line = link.append("line") .attr("class", "link") .style("stroke-width", "2"); //append a second, fatter line to g and make it invisible var fatline = link.append("line") .attr("class", "link") .attr("style", "stroke:transparent;stroke-width:10px"); //call for line coordinates for both lines force.on("tick", function() { line.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); fatline.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); }); 大小的包含

答案 2 :(得分:2)

成员的结构内部对齐不会影响该结构的数组。因此无论结构包含哪些成员或它们如何对齐,您所拥有的都可以保证有效。

如果结构的成员之间有填充,那么所有结构数组的元素都是相同的。 sizeof(array)始终可以整除sizeof(array[0])

所以计算数组大小的方法

size_t len = sizeof(array)/sizeof(array[0]);
只要array 数组

就可以保证适用于任何类型。

答案 3 :(得分:1)

sizeof宏返回结构的大小,包括所有填充。对于静态定义的struct数组,这仍然适用。所以声明:

sizeof(struct array) / sizeof(struct array[0])

无论每个struct元素中有多少成员或什么类型的成员,都将始终允许您遍历数组元素。

打包/对齐对数组边界没有影响
即使您的源中使用了 pragma pack 指令,也可能导致打包更改(这也会影响对齐),从而导致sizeof的值不同数组的每个struct元素, 数组元素的数量保持不变

...或者反例如果我的假设并不总是

重要的是要注意
sizeof运算符在结构(或任何其他类型)的数组上的工作方式不同,它们是在堆上动态创建的实际指针。例如,如果你有:

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(struct foo) / sizeof(struct foo[0])  

将不再为您提供正确的数组元素数。

答案 4 :(得分:1)

编译器可以在成员之间的任何地方及其末尾自由插入填充,但第一个成员的偏移量必须始终为零。

另一方面,阵列总是必须是连续的,没有任何&#34;间隙&#34;元素之间。该标准规定:

  

数组类型描述了连续分配的非空对象集

通常,大多数编译器会在结构的末尾插入一些填充,以确保在数组中连续布局时,第二个元素不会破坏某些成员的对齐要求。典型的规则是结构的总大小必须扩展到一个大小,该大小可以被成员的对齐方式整除,并具有最大的对齐要求。

在LP64模型中,sizeof(long)为8,sizeof(char)为1. long需要8字节对齐,char没有对齐要求。大小的总和将是9,但编译器会将结构的大小扩展为16,以便16 % 8 == 0。这样,相邻的数组元素将从8可被整除的位置开始,因此将保留第一个成员的对齐方式。