将正有符号整数输入为无符号整数(反之亦然)

Cac*_*ito 1 c unsigned signed language-lawyer type-punning

union   Positive_Small {
    int8_t  s;
    uint8_t u;
};

union Positive_Small    x = {.s = 3};
union Positive_Small    y = {.u = 4};

assert(x.u == 3);
assert(y.s == 4);
Run Code Online (Sandbox Code Playgroud)

这是定义的行为吗?标准是否保证有符号整数类型的正范围与其无符号等效项具有相同的表示?

我想没有足够疯狂的实现(可能是 DS9K?)不这样做,但它是否已定义?

Jon*_*ler 5

简而言之,是的 - 标准保证对于共享的正值范围,无符号类型的值的按位表示与有符号类型相同。

C11第 6.2.5 节类型定义了这一点(以及许多其他术语和行为):

¶6 对于每一种有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字指定unsigned),它使用相同的存储量(包括符号信息)并具有相同的对齐要求。_Bool与标准有符号整数类型对应的类型和无符号整数类型是标准无符号整数类型。与扩展有符号整数类型对应的无符号整数类型是扩展无符号整数类型。标准的和扩展的无符号整数类型统称为无符号整数类型40)

¶9 有符号整数类型的非负值范围是对应的无符号整数类型的一个子范围,每个类型中相同值的表示是相同的。41)涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果以比结果类型可以表示的最大值大 1 的数为模减少。

40)因此,本标准中关于无符号整数类型的任何声明也适用于扩展的无符号整数类型。

41)相同的表示和对齐要求意味着作为函数的参数、函数的返回值和联合成员的可互换性。

正如dbush 所 指出的第 6.2.6 节表示类型,以及第 6.2.6.2 节 Integer 类型,也包含相关信息:

¶2 对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;signed char不得有任何填充位。应该正好有一个符号位。作为值位的每个位应与相应无符号类型的对象表示中的同一位具有相同的值(如果有符号类型中有M 个值位,无符号类型中有N,则M ? N)。如果符号位为零,则不应影响结果值。如果符号位为 1,则应按以下方式之一修改该值:

  • 符号位为 0 的相应值被否定(符号和幅度);
  • 符号位的值为 -(2 M )(二进制补码);
  • 符号位的值为 -(2 M - 1) (一个的补码)。

其中哪一个适用是实现定义的,就像具有符号位 1 和所有值位为零(对于前两个),或具有符号位和所有值位 1(对于 1 的补码)的值是否是陷阱表示或正常值。在符号和幅度以及补码的情况下,如果此表示是正常值,则称为负零