你总能在C中访问包含结构数据的适当对齐的缓冲区吗?

Mar*_*eck 9 c c11

我在C中有结构类型的数据:

typedef struct {
  type0 field0;
  type1 field1;
} foo_struct;

foo_struct foo;
Run Code Online (Sandbox Code Playgroud)

现在假设我在虚拟内存中以某种方式分配了一个大小的缓冲区 sizeof(foo_struct)

char *buf = <some allocation method>
Run Code Online (Sandbox Code Playgroud)

然后我将数据从中复制foobuf,例如memcpy.

然后我想像这样访问字段buf:

((foo_struct *)buf)->fieldn
Run Code Online (Sandbox Code Playgroud)

这是否保证(通过C11标准)始终有效?

在另一个问题(关于不同的主题)中的人似乎在说,是的,这保证可行,特别是如果buf在页面边界上有良好对齐的话.

是的,它实际上是有保证的.但我认为,无论它是"对齐",页面边界或者不是这样,它都没有100%的标准保证.在那儿?

PSk*_*cik 7

你总能在C中访问包含结构数据的适当对齐的缓冲区吗?

如果缓冲区在动态内存中,则为是.

char *buf = malloc(1000000);
if(buf)
   ((foo_struct *)buf)->fieldn
Run Code Online (Sandbox Code Playgroud)

基本上就像

foo_struct *buf = malloc(1000000);
if(buf)
    buf->fieldn
Run Code Online (Sandbox Code Playgroud)

这保证有效.

如果缓冲区是静态分配的或自动的,那么没有.别名规则(6.5p7)阻止你做:

/*static*/ _Alignas(foo_struct) char buf[100000000];
foo_struct* foo_p = &buf;
if(foo_p)
    foo_p->fieldn
Run Code Online (Sandbox Code Playgroud)

即使缓冲区的对齐就足够了.

(注意:1后跟很多0 ==足够大)

  • @gowrath,因为如果对象的有效类型通过其分配具有类型,则它是固定的.您只能更改没有初始类型的对象的有效类型. (3认同)
  • @chux这不起作用,因为您无法在没有分配存储持续时间的情况下更改有效类型的对象. (2认同)

gow*_*ath 6

这有点取决于什么<some allocation method>.以下是关于malloc 的标准 [7.22.3]:

如果分配成功,则返回指针,以便可以将其分配给指向具有基本对齐要求的任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间被明确释放).

所以根据标准,你可以做你在使用malloc时所要求的.大多数其他编写良好的内存分配器也应满足此要求.