工会和类型双关语 [英] Unions and type-punning

查看:22
本文介绍了工会和类型双关语的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经搜索了一段时间,但找不到明确的答案.

I've been searching for a while, but can't find a clear answer.

很多人说使用联合来键入双关是未定义且不好的做法.为什么是这样?考虑到您将原始信息写入的内存不会自行更改(除非它超出堆栈范围,但这不是联合问题),我看不出它会做任何未定义的事情的任何原因,那将是糟糕的设计).

Lots of people say that using unions to type-pun is undefined and bad practice. Why is this? I can't see any reason why it would do anything undefined considering the memory you write the original information to isn't going to just change of its own accord (unless it goes out of scope on the stack, but that's not a union issue, that would be bad design).

人们引用严格的别名规则,但在我看来,这就像说你不能这样做,因为你不能这样做.

People quote the strict aliasing rule, but that seems to me to be like saying you can't do it because you can't do it.

如果不输入双关语,联合还有什么意义?我在某处看到它们应该用于在不同时间将相同的内存位置用于不同的信息,但为什么不在再次使用之前删除信息?

Also what is the point of a union if not to type pun? I saw somewhere that they are supposed to be used to use the same memory location for different information at different times, but why not just delete the info before using it again?

总结一下:

  1. 为什么使用联合来进行类型双关是不好的?
  2. 如果不是这个,它们还有什么意义?

额外信息:我主要使用 C++,但想了解它和 C.具体来说,我使用联合在浮点数和原始十六进制之间转换以通过 CAN 总线发送.

Extra information: I'm using mainly C++, but would like to know about that and C. Specifically I'm using unions to convert between floats and the raw hex to send via CAN bus.

推荐答案

重新迭代,通过联合进行类型双关在 C 中非常好(但在 C++ 中则不行).相反,使用指针强制转换违反了 C99 严格的别名,并且是有问题的,因为不同的类型可能有不同的对齐要求,如果你做错了,你可能会引发 SIGBUS.使用工会,这绝不是问题.

To re-iterate, type-punning through unions is perfectly fine in C (but not in C++). In contrast, using pointer casts to do so violates C99 strict aliasing and is problematic because different types may have different alignment requirements and you could raise a SIGBUS if you do it wrong. With unions, this is never a problem.

来自 C 标准的相关引用是:

The relevant quotes from the C standards are:

C89 第 3.3.2.3 节第 5 节:

C89 section 3.3.2.3 §5:

如果在将值存储到对象的不同成员之后访问联合对象的成员,则行为是实现定义的

if a member of a union object is accessed after a value has been stored in a different member of the object, the behavior is implementation-defined

C11 第 6.5.2.3 节第 3 节:

C11 section 6.5.2.3 §3:

后缀表达式后跟 .运算符和标识符指定结构或联合对象的成员.该值是命名成员的值

A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member

带有以下脚注 95:

如果用于读取联合对象内容的成员与上次用于在对象中存储值的成员不同,则将值的对象表示的适当部分重新解释为对象表示中的对象表示6.2.6 中描述的新类型(有时称为类型双关"的过程).这可能是一个陷阱表示.

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

这应该非常清楚.

James 很困惑,因为 C11 第 6.7.2.1 §16 节写道

James is confused because C11 section 6.7.2.1 §16 reads

任何时候最多可以将其中一个成员的值存储在联合对象中.

The value of at most one of the members can be stored in a union object at any time.

这似乎是矛盾的,但事实并非如此:与 C++ 相比,在 C 中,没有活动成员的概念,通过不兼容类型的表达式访问单个存储值是完全可以的.

This seems contradictory, but it is not: In contrast to C++, in C, there is no concept of active member and it's perfectly fine to access the single stored value through an expression of an incompatible type.

另见 C11 附件 J.1 §1:

See also C11 annex J.1 §1:

与最后存储到 [未指定] 的联合成员以外的联合成员相对应的字节值.

The values of bytes that correspond to union members other than the one last stored into [are unspecified].

在 C99 中,这用于读取

In C99, this used to read

存储到[未指定]中的最后一个以外的联合成员的值

The value of a union member other than the last one stored into [is unspecified]

这是不正确的.由于附件不规范,它没有对自己的 TC 进行评级,必须等到下一个标准修订版才能修复.

This was incorrect. As the annex isn't normative, it did not rate its own TC and had to wait until the next standard revision to get fixed.

标准 C++(和 C90)的 GNU 扩展明确执行允许使用联合进行类型双关.其他不支持 GNU 扩展的编译器也可能支持联合类型双关语,但它不是基础语言标准的一部分.

GNU extensions to standard C++ (and to C90) do explicitly allow type-punning with unions. Other compilers that don't support GNU extensions may also support union type-punning, but it's not part of the base language standard.

这篇关于工会和类型双关语的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆