在-255到255范围内,签名字符溢出是否未定义?

Nat*_*lin 2 c gcc c99

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

signed char c = CHAR_MAX; // assume CHAR_MAX < INT_MAX
c = c + 1;
printf("%d", c);
Run Code Online (Sandbox Code Playgroud)

ex *_*ilo 6

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

使用时c = c + 1,整数提升在添加之前执行,因此在右侧的表达式中c提升int.由于128小于INT_MAX,所以这种添加不会发生.请注意,char通常比窄int,但在罕见的系统charint可以是相同的宽度.在任何一种情况下,a char都被提升为int算术表达式.

时分配c,然后制成,如果滑动charunsigned在系统中的问题上,相加的结果小于UCHAR_MAX(必须是至少255),并且该值保持在转换和分配保持不变c.

如果char是plain signed,则signed char在赋值之前将加法的结果转换为值.这里,如果添加的结果不能signed char在转换"是实现定义的,或者实现定义的信号被引发"中表示,则根据标准的§6.3.1.3/ 3.SCHAR_MAX必须至少为127,并且如果是这种情况,则行为是实现定义在张贴代码值时平原charsigned.

对于相关代码,行为未定义,但是是实现定义的.


eca*_*mur 5

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

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

6.3.1.3 有符号和无符号整数

当整数类型的值转换为另一种整数类型时,[如果]新类型是有符号的并且该值不能用它表示[,]结果是实现定义的或引发实现定义的信号。

特别是,gcc 可以配置为视为char有符号或无符号 ( -f\[un\]signed-char);默认情况下,它会为目标平台 ABI 选择适当的配置(如果有)。如果选择了有符号字符,我所知道的所有当前 gcc 目标平台都有一个 8 位字节(一些过时的目标,如 AT&T DSP1600 有一个 16 位字节),所以它将有范围([-128, 127]8 位,两位)补码) 和 gcc将应用模算术产生-128结果:

当值无法在该类型的对象中表示时,将整数转换为有符号整数类型的结果或由此引发的信号(C90 6.2.1.2、C99 和 C11 6.3.1.3)。

为了转换为宽度为 N 的类型,该值会以 2^N 为模减少到该类型的范围内;没有发出任何信号。