【问题标题】:Compute address of struct field given struct address给定结构地址,计算结构字段的地址
【发布时间】:2019-12-04 00:16:11
【问题描述】:

给定一个打包(即假设没有对齐)结构:

struct Foo {
  int x;
  int y;
};

struct Foo *foo;

&foo->y 转换为foo + sizeof(int) 是否“安全”(即在标准中的某处定义)(即foo->y 的地址等于foo 的地址加上int 的大小) ?

我正在关注C11 standard6.2.6 Representations of types,但它没有说明字段如何存储在结构中。

【问题讨论】:

  • 这非常接近offsetof implementation。为什么不使用偏移量? (uintptr_t)(void*)foo + offsetof(struct Foo, y) ?
  • 谢谢,但我不能,因为我正在为C 实现一个玩具编译器。所以我想知道结构的数据布局是否在某处定义。
  • 难道不是由您的编译器来确定(缺少)填充吗?我认为这符合标准,但我不能引用任何内容。

标签: c struct compiler-construction


【解决方案1】:

作为编译器作者,可以选择任何填充的数量和大小。

标准规定您必须“按顺序”分配成员(第 6.2.5 节,第 20 段,第 42 页),并且除了位字段外,它们占用字节(6.2.6.1,第 44-45 页)。大多数情况下不需要太多其他东西。

(编辑:另一个要求是第一个成员的偏移量为零。请参阅第 6.7.2.1 节,第 15 段,第 113 页。)

ABI 可能会提出更严格的要求。一般来说,作为编译器编写者,您可能不应该插入“不必要的”填充,但您可以在此处定义“不必要的”。如果您支持某种形式的“打包”关键字或属性,请使用它来启用或禁用插入的填充以获得明显的性能提升(例如,在 4 字节边界上对齐 4 字节 int 的填充)。如果将 int 移动到 cache 行边界可能会提高性能,但可能不会,请将其留给用户。

【讨论】:

  • 另请注意,某些架构可能无法完全支持直接未对齐的内存访问;这不一定只是性能问题。除非询问者仔细编译内存访问以便未对齐的加载和存储正确执行,否则填充可能只是代码运行所必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多