使用 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" 值弱一些——语义相同,但平台不需要记录这些值是什么。)
考虑以下代码:
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 ofN
unsigned char
objects taken up by the object of typeT
, whereN
equalssizeof(T)
. The value representation of an object is the set of bits that hold the value of typeT
. 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 ofchar
orunsigned char
. If the content of the array ofchar
orunsigned char
is copied back into the object, the object shall subsequently hold its original value.
("unspecified" 值比 "implementation-defined" 值弱一些——语义相同,但平台不需要记录这些值是什么。)