在我的应用程序中,我使用了一个结构数组,我需要迭代数组。这样做的正确方法是什么?如何检查是否已到达阵列的末尾?
// structure
struct MyData {
int count;
char name[20];
float average;
}
我尝试过这样的迭代,但我的应用程序崩溃了:
struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
while (*ptr != NULL) {
// print the contents, works ok for 2 elements
ptr++; // increment the pointer
}
答案 0 :(得分:19)
在您的情况下,MyData[2]
数组在内存中看起来像这样:
| count | name | average | count | name | average |
^ -- your ptr points here
这是一个大小为3 * sizeof (struct MyData)
的单一连续空间。
每当执行ptr++
操作时,指针将移动到数组中的下一个结构,这意味着它会考虑单个struct MyData
的大小。
| count | name | average | count | name | average |
^ -- after ptr++ your ptr points here
在另一个ptr++
后,您的指针将指向数组之后的内存。
| count | name | average | count | name | average |
^ -- another ptr++ and your ptr points here
当您取消引用ptr
指针时,您将访问尚未使用或甚至已分配的内存。这是未定义的行为,因此您的应用程序崩溃。
有几种方法可以做到这一点。请注意,并非所有方式都适用于所有情况。
的简单说明
我们经常只知道数组的大小。然后我们可以使用普通的for
循环迭代内容。
int len = 2;
struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
for (int i=0; i<2; i++, ptr++ ) {
// do your thing with the ptr
// and note that ptr gets increased inside for
}
使用sizeof确定数组长度
struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
while ( ptr < endPtr ){
// do your thing with the ptr
ptr++;
}
sizeof(data)/sizeof(data[0])
计算元素的数量:获取数组的总大小,并将其除以单个元素的大小。
这种方法有其缺点。当数组声明为指针时,不能使用它!例如,当我们将数组作为参数传递给函数时,它通常会转换为指针 - 然后我们无法确定数组的大小。
答案 1 :(得分:1)
如果您对阵列的大小没有任何控制,甚至不能要求它,您可以尝试重新组织代码,而不是使用MyData
数组,而是使用指针数组至MyData
。
然后,您的数组必须长一个插槽才能存储NULL
值的保护。
您的迭代看起来就像您编写的那样。
// N is the number of MyData instances you have
MyData* vData[N+1];
// vData[i] is filled, and vData[N] = NULL
// ...
MyData* vPtr = vData[0];
while(vPtr) {
// ...
}
但这涉及将数组类型从MyData[]
更改为MyData*[]
。如果你不能,你应该遵循Dariusz的答案。