使用联合代替强制转换的定义是否明确?
今天早上我和一位同事讨论了检测字节顺序的“编码技巧”的正确性。
诀窍是:
bool is_big_endian()
{
union
{
int i;
char c[sizeof(int)];
} foo;
foo.i = 1;
return (foo.c[0] == 1);
}
对我来说,union
的这种用法似乎是不正确的,因为设置联合体的一个成员并读取另一个成员没有定义良好。但我不得不承认,这只是一种感觉,我缺乏实际证据来证实我的观点。
这个伎俩正确吗?谁在这里?
I had a discussion this morning with a colleague regarding the correctness of a "coding trick" to detect endianness.
The trick was:
bool is_big_endian()
{
union
{
int i;
char c[sizeof(int)];
} foo;
foo.i = 1;
return (foo.c[0] == 1);
}
To me, it seems that this usage of an union
is incorrect because setting one member of the union and reading another is not well-defined. But I have to admit that this is just a feeling and I lack actual proofs to strengthen my point.
Is this trick correct ? Who is right here ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的代码不可移植。它可能适用于某些编译器,也可能不适用于某些编译器。
当您尝试访问联合体的非活动成员时,您对未定义行为的看法是正确的[就像给出的代码的情况一样]
$9.5/1
因此
foo.c[0] == 1
是不正确的,因为c
此时未处于活动状态。如果您认为我错了,请随时纠正我。Your code is not portable. It might work on some compilers or it might not.
You are right about the behaviour being undefined when you try to access the inactive member of the union [as it is in the case of the code given]
$9.5/1
So
foo.c[0] == 1
is incorrect becausec
is not active at that moment. Feel free to correct me if you think I am wrong.不要这样做,最好使用如下所示的内容:
说明:
参考文献:
Don't do this, better use something like the following:
Explanation:
References:
您是对的,该代码没有明确定义的行为。以下是如何进行便携式操作:
You're correct that that code doesn't have well-defined behavior. Here's how to do it portably:
该函数应命名为 is_little_endian。我认为你可以使用这个联合技巧。或者也可以强制转换为 char。
The function should be named is_little_endian. I think you can use this union trick. Or also a cast to char.
该代码具有未定义的行为,尽管一些(大多数?)编译器会
至少在有限的情况下定义它。
该标准的意图是
reinterpret_cast
用于这。然而,这种意图并没有得到很好的表达,因为标准
无法真正定义行为;没有欲望定义它
硬件不支持它(例如由于对齐问题)。和
同样清楚的是,你不能只是在两个之间进行
reinterpret_cast
任意类型并期望它能够工作。
从实施质量的角度来看,我希望
union
技巧和reinterpret_cast
起作用,如果union
或reinterpret_cast
位于同一功能块中;工会
应该只要编译器可以看到最终类型是
union
就可以工作(尽管我使用过编译器,但情况并非如此)。
The code has undefined behavior, although some (most?) compilers will
define it, at least in limited cases.
The intent of the standard is that
reinterpret_cast
be used forthis. This intent isn't well expressed, however, since the standard
can't really define the behavior; there is no desire to define it when
the hardware won't support it (e.g. because of alignment issues). And
it's also clear that you can't just
reinterpret_cast
between twoarbitrary types and expect it to work.
From a quality of implementation point of view, I would expect both the
union
trick andreinterpret_cast
to work, if theunion
or thereinterpret_cast
is in the same functional block; theunion
shouldwork as long as the compiler can see that the ultimate type is a
union
(although I've used compilers where this wasn't the case).