【问题标题】:Which is the correct way to transfer values between unions?在工会之间转移价值的正确方法是什么?
【发布时间】:2018-04-21 16:08:39
【问题描述】:

如果你有:

typedef union value {
    int i;
    float f;
} VALUE;
VALUE a, b;

如果你知道a的类型,你应该知道吗

b.i = a.i;
b.f = a.f;

if(a_type == INT)
    b.i = a.i;
if(a_type == FLOAT)
    b.f = a.f;

【问题讨论】:

  • a 是什么? b 是什么? a_type 是什么?请出示minimal reproducible example
  • 不行,只有传入另一个参数才能知道要填什么。
  • 一般来说,如果成员ia 的活跃成员,您的代码就会出错。如果你真的不知道哪个成员是活跃的,你会遇到问题,但你仍然可以使用memcpymemcpy(&b, &a, sizeof b);
  • @mpez0: 所有位模式都对整数有效 不是 C 标准所保证的。在诸如较旧的 Cray 计算机之类的病态架构上,这种方法会失败。只需使用memcpy(&b, &a, sizeof b);

标签: c language-lawyer unions


【解决方案1】:

只需使用b = a,除非有特殊原因不使用,例如联合偶尔包含大量数据,并且您希望针对仅包含少量数据的情况优化分配。

根据 C 2011 [N1570] 6.5.16.1 1,简单分配的可接受情况之一是:

左操作数具有与右操作数兼容的结构或联合类型的原子、限定或非限定版本。

根据 6.2.7 1:

如果类型相同,则两种类型具有兼容的类型。

(根据 6.2.6.1 6,“结构或联合对象的值永远不是陷阱表示,即使结构或联合对象的成员的值可能是陷阱表示。”)

【讨论】:

    【解决方案2】:

    最正确的大概是(假设同类型)

    memcpy(&b, &a, sizeof(b));
    

    【讨论】:

    • 正确,建议删除 b 周围的括号作为 sizeof 参数...它们仅用于类型名称。
    • b = a 呢?
    • @FelixPalmen 我喜欢他们。这是我的风格。
    • 嗯,是的,sizeof 的典型样式是当参数是表达式时使用单个空格,而当参数是类型名称时使用不带空格的括号。但是,如果您坚持,请写任何您喜欢的内容:D
    • @PeterJ_01:完全没有危险,如果您在靠近 Linus Torvalds 的任何地方工作,实际上更安全:news.ycombinator.com/item?id=9629461
    【解决方案3】:

    标准没有指定在什么情况下可以通过非字符类型的成员访问左值访问与聚合关联的存储。如果联合成员 member1 是联合中最大的类型并且没有陷阱表示,则质量编译器应该能够处理类似的操作

    objectOfMemberType = someUnion.member1;
    someUnion.member1 = valueOfMemberType;
    

    高质量的编译器也应该对以下结构没有问题:

    memberType *p = &someUnion.member1;
    *p = valueOfMemberType;
    

    在编写标准时,如果成员是非字符类型,它对任一构造的行为没有要求,因此在不调用 UB 的情况下对联合执行任何操作的唯一方法是使用联合类型的左值复制联合的全部内容,使用字符类型的左值来访问联合的片段,或者使用像memcpy 这样的函数。直接通过成员左值访问联合内容在 gcc 和 clang 中似乎最可靠(我认为我发现它不是无意错误的情况)但 gcc 和 clang 似乎都没有被设计为可靠地支持任何联合成员指针的使用,即使使用立即遵循获取地址的行为[如上所示]。

    鉴于 C 标准的编写方式,很难真正确定在联合之间传输值的“正确”方式,因为大多数以有用的方式使用联合的代码都会调用 UB。哪种方法最好取决于哪种形式的 UB 愿意相信自己的编译器能够进行明智的处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-24
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多