使用 memcpy 将 int 复制到 char 数组,然后打印其成员:未定义的行为?

Using memcpy to copy an int into a char array and then printing its members: undefined behaviour?

考虑以下代码:

int i = 1;
char c[sizeof (i)];
memcpy(c, &i, sizeof (i));
cout << static_cast<int>(c[0]);

请忽略这是否是好的代码。我知道输出取决于系统的字节顺序。这只是一个学术问题。

是这个代码吗:

语言并没有说这样做是立即未定义的行为。它只是说 c[0] 的表示可能 最终成为无效(陷阱)表示,在这种情况下,行为确实是未定义的。但在 c[0] 不是陷阱表示的情况下,行为是实现定义的。

如果使用 unsigned char 数组,陷阱表示将变得不可能,行为将完全由实现定义。

这显然是实现定义的行为。

int 的内部表示不是由标准定义的(实现可以选择小端或大端或其他任何方式),因此它不能很好地定义行为:结果在不同的体系结构上允许不同。

在定义的系统(体系结构和 C 编译器以及(最终)配置)上,行为是完全确定的:在大端,你将得到 1,在小端,你将得到 0。所以它是 实现定义的行为.

您要查找的规则是 3.9p4:

The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.

因此,如果您使用 unsigned char,您确实会获得实现定义的行为(任何符合规范的实现都必须保证该行为是什么)。

通过char读取也是合法的,但是后面的值是未指定的。但是,根据 3.9p2:

,您可以保证使用不合格的 char 将保留该值(因此裸 char 不能有陷阱表示或填充位)

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or unsigned char. If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value.

("unspecified" 值比 "implementation-defined" 值弱一些——语义相同,但平台不需要记录这些值是什么。)