遍历C数组

51

我在程序的某个地方创建了一个结构体数组。

稍后,我想遍历它,但我不知道数组的大小。

我该如何遍历元素?或者我需要将大小存储在某个地方吗?

4个回答

64

如果在编译时已知数组的大小,您可以使用结构体大小来确定元素数量。

struct foo fooarr[10];

for(i = 0; i < sizeof(fooarr) / sizeof(struct foo); i++)
{
  do_something(fooarr[i].data);
}

如果在编译时不知道数组大小,那么你需要在某处存储数组大小或在数组末尾创建一个特殊的终止值。


8
确实,但我更倾向于使用 sizeof(fooarr[0])sizeof(*fooarr) 而不是 sizeof(struct foo) - gatopeich
1
这段代码无法编译,i 应该在初始赋值之前或与其同时声明。 - Pouriya Zarbafian

29

你可以将大小存储在某个位置,或者你可以使用一个结构体并设置特殊值作为哨兵值,就像\0表示字符串结尾的方式一样。


4
我通常使用指向结构体的指针,这样我就可以确保 NULL 是一个独特的标记。 - Chris Lutz
8
我认为遵循以空字符结尾的字符串模型是个不好的想法。 - hasen
1
@hasen j:我同意,除非你知道每次都必须遍历整个数组,否则哨兵可以稍微澄清代码。哨兵的问题在于你可能会得到O(N)的行为,而O(1)本来就可以做到,而且并不总是意识到这一点。 - quark

18

这要看情况而定。如果它是一个动态分配的数组,也就是说,您使用malloc创建了它,那么正如其他人建议的那样,您必须在某个地方保存数组的大小/元素数量,或者有一个哨兵(一个带有特殊值的结构体,将成为最后一个元素)。

如果它是一个静态数组,则可以使用sizeof获取其大小/每个元素的大小。例如:

int array[10], array_size;
...
array_size = sizeof(array)/sizeof(int);

请注意,除非是全局变量,否则它仅在初始化数组的范围内起作用,因为如果您将其传递给另一个函数,它就会被转换为指针。

希望这有所帮助。


6
重点不在于数组是否动态分配,而在于你是否允许数组类型退化为指针类型。例如,我可以这样创建一个动态分配的数组:int (*a)[10] = malloc(sizeof *a),并使用 sizeof *a / sizeof **a 后面的表达式来“确定”元素数量,无需额外储存数组大小。 - AnT stands with Russia
8
+1,尽管稍微更好的做法是使用sizeof(array)/sizeof(array[0]),这样即使基础数组类型发生变化仍然有效。这种形式还允许您轻松定义宏,例如 #define ARRAY_COUNT(a) (sizeof(a)/(sizeof(a[0]))) - Adam Rosenfield
同样的道理也适用于将其传递给函数。这完全取决于您如何传递它。 - AnT stands with Russia
@AdamRosenfield:那应该就是一个答案了。(然后我可以编辑它来添加缺失的括号...) - endolith

1

我认为你应该在某个地方存储大小。

以空字符结尾的字符串模型来确定数组长度是一个糟糕的想法。例如,获取数组的大小将是O(N),而本可以很容易地变成O(1)。

话虽如此,一个好的解决方案可能是glib's Arrays,它们有自动扩展的优点,如果需要添加更多项。

P.S.老实说,我没有使用过太多glib,但我认为它是一个(非常)值得信赖的库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接