我总是使用以下范例来迭代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) == 7
而sizeof(array) == 32
?
答案 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
可被整除的位置开始,因此将保留第一个成员的对齐方式。