【问题标题】:Get sizeof anonymous struct inside union在联合中获取 sizeof 匿名结构
【发布时间】:2014-05-07 18:46:42
【问题描述】:

我希望这不是一个重复的问题,但我已经进行了一些详细的搜索,但之前没有找到我的确切情况。

我有一个简单的结构,我也希望能够以简单的字节数组的形式访问它

union
{
  struct
  {
    unsigned char a;
    unsigned char b;
    // ... Some other members ...
    unsigned char w;
  };
  unsigned char bytes[sizeof( what? )];
} myUnion;

请注意,该结构没有命名,也没有给出自己的成员名称。这样我就可以使用myUnion.a 访问该成员,而不是myUnion.myStruct.a

但是,如果没有名称,除了每次更改内容时手动计算之外,我如何获取 myUnion.bytes[] 的结构大小?

我目前的解决方法是使用#define 来弥补myUnion.myStruct 的问题,但这具有破坏我在编辑器中的自动完成功能的负面影响,并且也使我的数据结构更难理解.

有什么想法吗?

注意:这是在 8 位处理器上运行的。单词对齐等没有问题。也就是说,可能应该说明任何警告,以免其他人不恰当地使用建议的解决方案。

【问题讨论】:

  • 使用 offsetof()。 cplusplus.com/reference/cstddef/offsetof。 imo会得到任何错误的结果。
  • 这不是 union 应该使用的方式,而且非常危险。如果你幸运的话,编译器不会在你的结构中添加任何填充,它会工作。
  • @RedAlert 您可以“询问编译器”而不是在元素之间添加填充,但每当您看到类似的内容时,您应该假设它不会是可移植的。
  • 旁注:标准 C++ 中不允许在联合/其他类中使用匿名结构。它们甚至在 C99 中都不允许,最后 C11 增加了对它们的(官方)支持。 g++ 和 clang++ 支持它们作为语言扩展。
  • 我认为只有一个普通的结构会简单得多;然后通过强制转换或函数调用以bytes 的身份访问它。您使用的非标准结构和技巧越少,您在路上遇到的麻烦就越少

标签: c++ c struct sizeof unions


【解决方案1】:

只要摆脱工会。通过将其地址转换为char*,您可以安全地以字节数组的形式访问任何可简单复制的结构,并且当您从非活动的联合成员中读取数据时,转换不会与未定义的行为发生冲突。

struct
{
    unsigned char a;
    unsigned char b;
    // ... Some other members ...
    unsigned char w;

    // array-style access
    unsigned char& operator[](size_t i)
    { return reinterpret_cast<unsigned char*>(this)[i]; }
} myStruct;

以这种方式进行转换是安全的原因是 char 是严格别名限制的一个特殊例外。

对于联合体,您获得的唯一特殊权限是访问“共享公共初始序列的标准布局结构”的成员......不幸的是,数组不符合“标准布局结构”的标准”。我希望看到该规则更改为“标准布局结构或聚合”,但在当前措辞中,联合版本并不安全。


在 C99 中,但不是任何版本的 C++,您可以使用灵活的数组成员,并且根本不需要指定大小。

union
{
  struct
  {
    unsigned char a;
    unsigned char b;
    // ... Some other members ...
    unsigned char w;
  };
  unsigned char bytes[];
} myUnion;

【讨论】:

  • 是的,这看起来更理智,......甚至只是使用字节数组
  • 看起来我没有使用 C99,因为在尝试第二种解决方案时出现错误“联合中的灵活数组成员”。第一个似乎需要 C++ 作为语法糖,但基本前提应该适用于我使用 #define myStructBytes ((char *)myStruct) 或类似的东西。谢谢!
  • @gkimsey:我没有测试它,所以这可能是 C99 中你不能成为灵活数组成员的地方之一。编译器将其识别为这一事实非常具有启发性。 TonyK 使用 1 大小的版本是一个合理的解决方法,可能适用于大多数编译器,但我认为它确实违反了规则。
  • n1570 6.7.2.1/18 "作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。”因此,这似乎确实是非法的。 (编辑:...看到编辑太晚了)
【解决方案2】:

这将起作用:

union
{
  struct
  {
    unsigned char a;
    unsigned char b;
    // ... Some other members ...
    unsigned char w;
  };
  unsigned char bytes[1];
} myUnion;

【讨论】:

  • 我曾考虑过这一点,并假设如果我在代码中的某处执行myUnion.bytes[2],编译器会抱怨,但我只是尝试过,但没有。我想我会用这个,虽然它可能不是很便携。
  • 这是一个使用此解决方案的ideone,如果它对任何人都有好处。 ideone.com/MDnXC6
  • @gkimsey:它是 100% 可移植的。表达式myUnion.bytes[2]*(myUnion.bytes+2) 相同,是明确的。
【解决方案3】:

您将无法为以前的匿名结构命名。

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 2014-10-21
    • 1970-01-01
    • 2019-06-01
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2011-07-01
    相关资源
    最近更新 更多