联盟uint32_t的和uint8_t有[4]未定义行为? [英] union for uint32_t and uint8_t[4] undefined behavior?

查看:1668
本文介绍了联盟uint32_t的和uint8_t有[4]未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在href=\"http://stackoverflow.com/a/8568531/1025391\">这个答案有人说,这将是未定义行为一个整数分解成其字节

 工会地址{
 uint8_t有addr8 [4];
 uint32_t的addr32;
};

到现在为止我认为这将是罚款的方式做这样的事情地址= {127,0,0,1}; ,并得到相应的 uint32_t的的回报。 (我承认这可能会根据我的系统的字节序产生不同的结果。然而,问题仍然存在。)

这是不确定的行为?如果是这样,为什么? (我不知道是什么意思的什么是UB在C ++中是访问不活跃工会会员。的)


C99


  • C99是apparantly pretty接近C ++ 03在这一点上。

C ++ 03


  • <青霉>在联合中,数据成员的至多一个可以在,也就是,数据成员的至多一个的值可以在任何时间被存储在一个联合的任何时间是活动的。 C ++ 03,第9.5(1),162页

然而


  • 如果POD联合包含几个POD-结构共享一个通用初始序列[...]它允许检查任何POD结构成员的公共初始序列的同上。

  • 两个POD结构[...]类型是布局兼容的,如果他们有相同数量的非静态数据成员,并且对应的非静态数据成员(按顺序)具有布局兼容的类型的ç ++ 03,第9.2节(14),第157页

  • 如果两个类型T1和T2是相同的类型,那么T1和T2是布局兼容的类型。的C ++ 03,第3.9(11),53页

结论


  • uint8_t有[4] uint32_t的是不是同一类型(我想,一个的strict走样的事情)(加两个不是POD-结构/联合)上面确实UB?

C ++ 11


  • 需要注意的是聚合类型不包括联合类型,因为与工会类型的对象只能包含一次一个成员。的C ++ 11,46脚注,42页


解决方案

  

我不知道是什么意思有什么UB在C ++中是访问不活跃工会会员。


基本上它的意思是,你可以从工会阅读,而不必调用未定义行为的唯一成员是最后写了一个。换句话说,如果你写 addr32 ,你只能从 addr32 阅读,而不是 addr8 ,反之亦然。

一个例子也可以这里

编辑:既然已经有很多的讨论,如果这是UB与否,考虑下面的(完全有效)C ++ 11的例子;

 工会欧莱{
    性病::字符串str;
    的std :: wstring的WSTR;
};

在这里你绝对可以看到,激活海峡和阅读WSTR可能是一个问题。你可以认为这是一个极端的例子,因为你甚至有做一个放置新激活的成员,但该规范实际上涵盖这种情况下没有提到它的被认为是对活跃会员等方式的特殊情况。

In the comments of this answer it is said that it would be undefined behavior to split up an integer into their bytes using a union like follows. The code given at that place is similar though not identical to this, please give a note if have I changed undefined-behavior-relevant aspects of the code.

union addr {
 uint8_t addr8[4];
 uint32_t addr32;
};

Up to now I thought this would be a fine approach to do things like addr = {127, 0, 0, 1}; and get the corresponding uint32_t in return. (I acknowledge that this may yield different results depending on the endianness of my system. The question however remains.)

Is this undefined behavior? If so, why? (I don't know what means What's UB in C++ is to access inactive union members.)


C99

  • C99 is apparantly pretty close to C++03 in this point.

C++03

  • In a union, at most one of the data members can be active at any time, that is, the value of at most one of the data members can be stored in a union at any time. C++03, Section 9.5 (1), page 162

However

  • If a POD-union contains several POD-structs that share a common initial sequence [...] it is permitted to inspect the common initial sequence of any of POD-struct members ibid.
  • Two POD-struct [...] types are layout-compatible if they have the same number of nonstatic data members, and corresponding nonstatic data members (in order) have layout-compatible types C++03, Section 9.2 (14), page 157
  • If two types T1 and T2 are the same type, then T1 and T2 are layout-compatible types. C++03, Section 3.9 (11), page 53

Conclusion

  • as uint8_t[4] and uint32_t are not the same type (I guess, a strict aliasing thing) (plus both not being POD-structs/union) the above is indeed UB?

C++11

  • Note that aggregate type does not include union type because an object with union type can only contain one member at a time. C++11, Footnote 46, page 42

解决方案

I don't know what means What's UB in C++ is to access inactive union members.

Basically what it means is that the only member you can read from a union without invoking undefined behavior is the last written one. In other words, if you write to addr32, you can only read from addr32, not addr8 and vice versa.

An example is also available here.

Edit: Since there has been much discussion if this is UB or not, consider the following (fully valid) C++11 example;

union olle {
    std::string str;
    std::wstring wstr;
};

Here you can definitely see that activating str and reading wstr may be a problem. You could see this as an extreme example since you even have to activate the member by doing a placement new, but the spec actually covers this case with no mention that it's to be considered a special case in other ways regarding active members.

这篇关于联盟uint32_t的和uint8_t有[4]未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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