C 结构是否将其成员保存在连续的内存块中?

Dav*_*ick 4 c

假设我的代码是:

typedef stuct {
  int x;
  double y;
  char z;
} Foo;
Run Code Online (Sandbox Code Playgroud)

xy以及z,在内存旁边对方?指针算术可以“迭代”它们吗?我的 C 生锈了,所以我不能完全正确地测试这个程序。这是我的完整代码。

#include <stdlib.h>
#include <stdio.h>

typedef struct {
  int x;
  double y;
  char z;
} Foo;


int main() {
  Foo *f = malloc(sizeof(Foo));
  f->x = 10;
  f->y = 30.0;
  f->z = 'c';
  // Pointer to iterate.
  for(int i = 0; i == sizeof(Foo); i++) {
    if (i == 0) {
      printf(*(f + i));
    }
    else if (i == (sizeof(int) + 1)) {
      printf(*(f + i));
    }
    else if (i ==(sizeof(int) + sizeof(double) + 1)) {
      printf(*(f + i));
    }
    else {
      continue;
    }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*lli 14

不,不能保证struct成员在内存中是连续的。

从 C 标准中的第 6.7.2.1 点第 15 点开始(此处为第 115 页):

结构对象内可能有未命名的填充,但不是在其开头。

大多数时候,类似于:

struct mystruct {
    int a;
    char b;
    int c;
};
Run Code Online (Sandbox Code Playgroud)

确实与 对齐sizeof(int),如下所示:

 0  1  2  3  4  5  6  7  8  9  10 11
[a         ][b][padding][c          ]
Run Code Online (Sandbox Code Playgroud)


Kei*_*son 10

是和否。

是的,结构的成员被分配在一个连续的内存块中。在您的示例中,类型的对象Foo占用sizeof (Foo)内存的连续字节,并且所有成员都在该字节序列内。

但是不,不能保证成员本身彼此相邻。任何两个成员之间或最后一个成员之后都可以有填充字节。该标准确实保证第一个定义的成员位于偏移量 0 处,并且所有成员都按照定义的顺序分配(这意味着有时可以通过对成员重新排序来节省空间)。

所以你不能(直接)迭代结构的成员。如果您想这样做,并且所有成员都属于同一类型,请使用数组。

可以使用offsetof定义在 中的宏<stddef.h>来确定(非位域)成员的字节偏移量,有时使用它来构建可用于迭代结构成员的数据结构会很有用。但它很乏味,而且很少比简单地按名称引用成员更有用——特别是如果它们具有不同的类型。