下面用于测试字节顺序的代码预计具有实现定义的行为:
int is_little_endian(void) {
int x = 1;
char *p = (char*)&x;
return *p == 1;
}
但它是否有可能在特意设计的架构上具有未定义的行为?例如,表示的第一个字节可以是int
有价值1
(或另一个精心选择的值)是陷阱值char
type?
正如评论中所述,类型unsigned char
不会有这个问题,因为它不能有陷阱值,但这个问题特别涉及char
type.
根据 C 2018 6.2.5 15,char
表现为signed char
or unsigned char
。假设是signed char
。 6.2.6.2 2 讨论有符号整数类型,包括signed char
。在这一段的最后,它说:
这些之中的哪一个 [符号和大小, 补码, or 一个的补语] 应用是实现定义的,就像符号位为 1 且所有值位为零(对于前两个)的值,还是符号位和所有值位为 1(对于补码)的值是陷阱表示还是陷阱表示正常值。
因此,本段允许signed char
有一个陷阱表示。然而,标准中的段落 6.2.6.1 5 指出访问陷阱表示可能具有未定义的行为,特别排除了字符类型:
某些对象表示不需要表示对象类型的值。如果对象的存储值具有此类表示形式,并且由不具有字符类型的左值表达式读取,则行为未定义。如果这样的表示是由副作用产生的,即通过不具有字符类型的左值表达式修改对象的全部或任何部分,则行为是未定义的。这种表示称为陷阱表示。
因此,虽然char
可能有陷阱表示,我们没有理由不能访问它。那么问题来了,如果我们在表达式中使用该值会发生什么?如果一个char
有一个陷阱表示,它不表示一个值。所以尝试将其与 1 in 进行比较*p == 1
似乎没有定义的行为。
1 的具体值int
不会导致陷阱表示char
对于任何正常的 C 实现,因为 1 将位于某个字节的“最右边”(最低值)位int
,并且没有正常的 C 实现会放置 a 的符号位char
在那个位置的位上。然而,C 标准显然并不禁止这样的安排,因此,理论上,int
值 1 可能会在其字节之一中使用位 00000001 进行编码,并且这些位可能是一个陷阱表示char
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)