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

Nei*_*irk 6 c++ language-lawyer

请考虑以下代码:

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

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

这段代码是:

  • 未定义的行为
  • 实现定义的行为
  • 定义明确的行为
  • 还有别的

AnT*_*AnT 6

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

如果使用unsigned char数组,则陷阱表示变得不可能,行为变为纯粹的实现定义.

  • @Neil Kirk:不."unsigned char"没有陷阱表示. (2认同)

Ben*_*igt 3

您正在寻找的规则是 3.9p4:

类型对象的对象表示是类型对象所占用的对象T序列,其中 equals 。对象的值表示是保存 type 值的一组位。对于普通可复制类型,值表示是对象表示中确定值的一组位,该值是实现定义的值集的一个离散元素。N unsigned charTNsizeof(T)T

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

通读char也是合法的,但值是未指定的。然而,根据 3.9p2,您可以保证使用 unqualifiedchar将保留该值(因此 bare不能有陷阱表示或填充位):char

对于普通可复制类型 T 的任何对象(基类子对象除外),无论该对象是否持有类型 的有效值T,组成该对象的底层字节 (1.7) 都可以复制到char或的数组中unsigned charchar如果或数组的内容unsigned char被复制回对象中,则该对象随后应保留其原始值。

(“未指定”值比“实现定义”值稍弱——语义相同,但平台不需要记录这些值是什么。)