【问题标题】:C struct: consecutive fields without padding?C struct:没有填充的连续字段?
【发布时间】:2013-07-21 05:42:30
【问题描述】:

any_t 是任何类型(intstruct something、...)。

考虑这个结构:

struct my_struct {
    any_t val,
    any_t array[10]
}

如果我定义一个变量v:

struct my_struct v;

&v.val 用作包含11 个any_t 项的数组是否安全?

any_t *p = &v.val;
f(p[0]);
f(p[5]);
f(p[10]);

是否保证valarray 之间不会添加填充?

【问题讨论】:

标签: c struct padding


【解决方案1】:

仅从 C 标准来看,将 &v.val 用作 11 个 any_t 的数组是不安全的,原因如下:

  • C 标准允许在结构中使用未命名的内部填充:C 2011 (N1570) 6.7.2.1 15,“结构对象中可能存在未命名的填充,但不是在其开头。” C 实现在valarray 之间插入填充是不寻常的,因为对齐要求不需要它,但它是允许的,并且在某些情况下它可能是有益的,例如使array 更好与性能(而非必要性)保持一致。
  • 即使保证valarray 元素的间距与11 个any_t 的数组相同,也不能保证指针算术有效。 C 2011 (N1570) 6.5.6 8 定义了指针算术(包括数组索引),它只要求算术工作在数组内(包括最后一个名义元素)。一些 C 实现使用基址和偏移寻址。在这种情况下,val 的基地址可能无法支持扩展到 array 的偏移量。
  • 即使 C 实现使用简单的平面寻址,它的优化器也可以根据 C 标准进行推导。理论上,优化器可以看到一个指针源自val 的地址,因此不能(根据C 标准)用于寻址array 中的任何内容。例如,如果您执行了any_t *p = &v.val; p[i] = 3; v.array[j] = 4;,优化器可能会将分配给v.array[j]p[i] 视为独立并以任何顺序执行它们,即使您可能已设置ij 以便它们指向到同一个元素。

【讨论】:

  • 对于超出数组声明大小的指针的实现可以或不能合法地做什么,该标准似乎有点模糊;到目前为止,我还不知道有什么可以证明或反对“struct hack”的“传统”版本(使用大小为一的数组)。然而,关于你的后一点,我认为如果一个结构在 malloc 的空间内,将一个元素的地址转换为 void* 然后回到它的元素类型应该保证事情应该工作,如果事情是实际上位于正确的位置。
  • 除非指定了特定的实现,否则我认为没有任何可移植的方式来对结构成员使用数组式访问,除非已经定义了明确列出的结构成员的偏移数组(以及其他事情,不能保证成员将是等距的),但我认为如果一个结构在 malloc 的空间内,它保证它的成员与其中的适当字节重叠。
  • 使用关于地址空间的模型来推理 C 语义是不正确的(例如,考虑到成员将处于某些字节偏移,因此它们形成一个数组),因为 C 标准没有定义这样的一个模型。为了正确推理,您必须从标准中的陈述中推断出行为。正如我所指出的,优化器可以做意想不到的事情。即使您使用malloc 分配空间,设置v 指向它,并且所有元素都在预期的偏移量,如果您设置any_t *p = &v->val,那么优化器被允许表现得好像p[i] 不是v->array[j].
【解决方案2】:

不,标准没有任何保证。但是,您的特定编译器实现肯定会做出超出标准的保证。查看您的文档以了解所有详细信息。

【讨论】:

  • 对齐要求不相关。 valarray 成员将具有相同的对齐要求,因此由对齐要求引起的 val 填充将与由对齐要求引起的 array 元素填充相同。该标准允许在valarray 之间使用未命名的填充,但实现不会为对齐要求插入填充。 (假设它可能会插入填充以获得对齐优势,例如,如果它有助于将 array 与缓存行对齐,并且编译器有理由相信这将是有益的。)
  • 还不错;删除第二句。
【解决方案3】:

您对结构的定义大约是 2 个字段,因此您的编译器可能不会将其用作 11 个元素的数组,因此您必须在文件被清除时填写它们。

【讨论】:

    猜你喜欢
    • 2019-01-01
    • 1970-01-01
    • 2022-01-26
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 2015-05-30
    • 2023-03-18
    相关资源
    最近更新 更多