16

在我的应用程序中,我使用了一个结构数组,我需要遍历该数组。正确的方法是什么?如何检查我是否已到达数组的末尾?

// 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
}
4

2 回答 2

28

如何分配结构数组

在您的情况下,MyData[2]数组在内存中如下所示:

| count | name | average | count | name | average |
^ -- your ptr points here 

这是一个大小为 的单个连续空间2 * 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<len; 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])元素的数量:获取数组的总大小并将其除以单个元素的大小。

这种方法有其缺点。数组声明为指针时不能使用!例如,当我们将数组作为参数传递给函数时,它通常会转换为指针 - 然后我们无法确定数组的大小。

于 2013-09-20T10:52:18.590 回答
2

如果您对数组的大小没有任何控制权,甚至不能要求它,您可以尝试重新组织您的代码,而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 的回答。

于 2013-09-20T11:54:18.967 回答