signed char 溢出是否在 -255 到 255 范围内未定义?

Is signed char overflow undefined within the range -255 to 255?

根据 C99 模式下的 GCC,以下代码是否未定义行为:

signed char c = CHAR_MAX; // assume CHAR_MAX < INT_MAX
c = c + 1;
printf("%d", c);

不,它具有实现定义的行为,要么存储实现定义的结果,要么可能发出信号。

首先,对操作数应用通常的算术转换。这会将操作数转换为 int 类型,因此计算以 int 类型执行。结果值 128 保证可以在 int 中表示,因为 INT_MAX 保证至少为 32767(5.2.4.2.1 整数类型的大小 ),因此接下来类型 int 中的值 128 必须转换为类型 char 才能存储在 c 中。如果 char 是无符号的,则 CHAR_MAX 保证至少为 255;否则,如果 SCHAR_MAX 取其最小值 127:

6.3.1.3 Signed and unsigned integers

When a value with integer type is converted to another integer type, [if] the new type is signed and the value cannot be represented in it[,] either the result is implementation-defined or an implementation-defined signal is raised.

特别是,gcc 可以配置为将 char 视为有符号或无符号(-f\[un\]signed-char); by default it will pick the appropriate configuration for the target platform ABI, if any. If a signed char is selected, all current gcc target platforms that I am aware of have an 8-bit byte (some obsolete targets such as AT&T DSP1600 had a 16-bit byte), so it will have range [-128, 127] (8-bit, two's complement) and gcc will apply modulo arithmetic 产生 -128 作为结果:

The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 and C11 6.3.1.3).

For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.

signed char 溢出确实会导致未定义的行为,但发布的代码中不会发生这种情况。

对于c = c + 1,整数提升是在加法之前进行的,因此在右边的表达式中c被提升为int。因为 128 小于 INT_MAX,所以这个加法没有发生意外。请注意 char 通常比 int 窄,但在极少数系统上 charint 可能宽度相同。在任何一种情况下,在算术表达式中 char 都会被提升为 int

然后对 c 进行赋值时,如果普通 char 在有问题的系统上是 unsigned,则加法的结果小于 UCHAR_MAX (必须至少为 255)并且此值在转换和分配给 c.

时保持不变

如果普通 charsigned,则加法的结果在赋值前转换为 signed char 值。在这里,如果加法的结果不能用 signed char 表示,则根据标准的 §6.3.1.3/3 进行转换 "is implementation-defined, or an implementation-defined signal is raised,"SCHAR_MAX 必须至少为 127,如果是这种情况,则当纯 charsigned.

时,行为是针对已发布代码中的值实现定义的

相关代码的行为不是未定义的,而是实现定义的。