根据GCC在C99模式下,以下代码是否未定义行为:
signed char c = CHAR_MAX; // assume CHAR_MAX < INT_MAX
c = c + 1;
printf("%d", c);
答案 0 :(得分:6)
signed char
溢出确实会导致未定义的行为,但这不是发布的代码中发生的情况。
使用c = c + 1
,整数提升会在添加之前执行,因此c
会在右侧的表达式中提升为int
。由于128
小于INT_MAX
,因此这种添加不会发生意外。请注意,char
通常比int
窄,但在稀有系统上char
和int
的宽度可能相同。在任何一种情况下,char
都会在算术表达式中提升为int
。
当对c
进行分配时,如果相关系统上的char
为unsigned
,则添加结果小于UCHAR_MAX
(其中必须至少为255)并且此值在转换和分配到c
时保持不变。
如果明确char
为signed
,则在分配之前,添加的结果将转换为signed char
值。在此,如果根据标准的§6.3.1.3/ 3,无法在signed char
转化"is implementation-defined, or an implementation-defined signal is raised,"中表示添加结果。 SCHAR_MAX
必须至少为127,如果是这种情况,那么当普通char
为signed
时,行为是针对已过帐代码中的值实现定义的。
对于相关代码,行为未定义,但是是实现定义的。
答案 1 :(得分:4)
不,它具有实现定义的行为,要么存储实现定义的结果,要么可能产生信号。
首先,通常的算术转换应用于操作数。这会将操作数转换为类型int
,因此计算将在类型int
中执行。结果值128
保证在int
中可表示,因为INT_MAX
保证至少为32767( 5.2.4.2.1整数类型的大小 ),接下来,类型128
中的值int
必须转换为char
类型才能存储在c
中。如果char
未签名,则CHAR_MAX
保证至少为255;否则,如果SCHAR_MAX
取其最小值127:
6.3.1.3有符号和无符号整数
当一个整数类型的值转换为另一个整数类型时,[if]新的类型被签名并且值无法在其中表示[,] 结果是实现定义的或引发实现定义的信号。
特别是,gcc可以配置为将char
视为有符号或无符号(-f\[un\]signed-char
);默认情况下,它将为目标平台ABI选择适当的配置(如果有)。如果选择了signed char,我所知道的所有当前gcc目标平台都有一个8位字节(一些过时的目标,如AT&amp; T DSP1600有一个16位字节),因此它的范围为{{1} }(8位,two's complement)和gcc will apply modulo arithmetic产生[-128, 127]
的结果:
当该值无法在该类型的对象中表示时,将整数转换为有符号整数类型的结果或引发的信号(C90 6.2.1.2,C99和C11 6.3.1.3)。为了转换为宽度为N的类型,将该值减去模2 ^ N以在该类型的范围内;没有信号被提出。