是否将设置为CHAR_MAX的char值保证可以绕回CHAR_MIN?


10

我的代码:

#include <stdio.h>
#include <limits.h>

int main()
{
    char c = CHAR_MAX;
    c += 1;
    printf("CHAR_MIN=%d CHAR_MAX=%d c=%d (%c)\n", CHAR_MIN, CHAR_MAX, c, c);
}

输出:

CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()

我们看到,当我们将char变量设置为递增时CHAR_MAX,它会绕到CHAR_MIN。这种行为得到保证吗?还是将是未定义的行为或实现特定的行为?C99标准对此有何说法?

[注意:当给charC 大于CHAR_MAX(127)的值时会发生什么?为什么char c = 129会转换为-127?之所以没有解决这个问题,是因为他们谈论分配超出范围的值,而不是将值递增到超出范围的值。]


增量是一项分配。
威廉·珀塞尔

2
这取决于字符是带符号的还是无符号的。有符号整数的溢出是未定义的行为。所以输出可以是任何东西。
达伯勒

Answers:


15

问题是双重的:首先,是

char c = CHAR_MAX;
c += 1;

评估结果与

char c = CHAR_MAX;
c = c + 1;

答案是否定的,不是,因为C11 / C18 6.5.16.2p3

  1. 形式的复合赋值E1 op = E2与简单赋值表达式等效,E1 = E1 op (E2)除了左E1值仅被评估一次,并且对于不确定顺序的函数调用,复合赋值的操作是单个求值。如果E1具有原子类型,则复合分配是具有memory_order_seq_cst内存顺序语义的读-修改-写操作。113)

然后,问题是发生了什么c = c + 1。这里的操作数+进行通常的算术转换,并且c1因此被提拔到int,除非实在古怪的架构要求char被提升为unsigned int。的计算+然后被评价,结果,类型的int/ unsigned int被转换回char并存储在c

可以通过3种实现定义的方式对其进行评估:

  • CHAR_MIN是0,因此char是无符号的。

    要么char然后被提升为int或者unsigned int,如果它被提升到一个int,那么CHAR_MAX + 1必然会融入了int太多,也不会溢出,或者unsigned int它可能适合或环绕到零。当所得值(在数值上CHAR_MAX + 10模减少后)回到c模减少后,它将变为0,即CHAR_MIN

  • 否则char进行签名,如果CHAR_MAX 小于INT_MAX,则的结果CHAR_MAX + 1将适合int,并且标准C11 / C18 6.3.1.3p3适用于分配时发生的转换:

    1. 否则,将对新类型进行签名,并且无法在其中表示值;结果是实现定义的,还是引发实现定义的信号。
  • 或者,如果iff sizeof (int) == 1 和带 char符号,则将char其提升为int,并且CHAR_MAX == INT_MAX=> CHAR_MAX + 1将导致整数溢出,并且行为未定义

即可能的结果是:

  • 如果char为无符号整数类型,则结果始终为0,即CHAR_MIN

  • 否则char为有符号整数类型,并且行为是实现定义的/未定义的:

    • CHAR_MIN 或其他一些实现定义的值,
    • 产生一个实现定义的信号,可能终止程序,
    • 或在某些平台上未定义行为sizeof (char) == sizeof (int)

所有的增量业务c = c + 1c += 1c++并且++c具有相同的平台上相同的副作用。表达式的计算值c++将是c增量之前的值;对于其他三个,它将是c增量之后的值。


1
sizeof(int) == 1会要求CHAR_BITS >= 16吧?
sepp2k

3
@ sepp2k <pedantic>IDK大约,CHAR_BITS但是CHAR_BIT>= 16</pedantic>
Antti Haapala

2
char默认情况下始终应未签名的另一个原因。
chqrlie

1
@chqrlie我同意,不幸的是,它可能是默认签名的,因为unsigned是历史上较晚的版本,在某些cr * ppy系统上现在可能很难更改,因为大量的破损程序希望EOF能够适合char ..
Antti Haapala

1
有时也很明显地添加一个直接答案:“是否将设置为CHAR_MAX的char值保证可以环绕到CHAR_MIN?” ->否
chux-恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.