设置为 CHAR_MAX 的 char 值是否保证环绕到 CHAR_MIN?

Is a char value set to CHAR_MAX guaranteed to wrap around to CHAR_MIN?

我的代码:

#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 标准对此有何规定?

[注意:What happen when give value bigger than CHAR_MAX (127) to char or C- why char c=129 will convert into -127? 没有解决这个问题,因为他们谈论的是分配一个超出范围的值,而不是将一个值递增到一个超出范围的值。]

问题有两个:首先,是

char c = CHAR_MAX;
c += 1;

评价不同于

char c = CHAR_MAX;
c = c + 1;

答案是不,不是,因为C11/C18 6.5.16.2p3:

  1. A compound assignment of the form E1 op = E2 is equivalent to the simple assignment expression E1 = E1 op (E2) except that the lvalue E1 is evaluated only once, and with respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. If E1 has an atomic type, compound assignment is a read-modify-write operation with memory_order_seq_cst memory order semantics. 113)

那么,问题是c = c + 1中会发生什么。这里 + 的操作数经过通常的算术转换,因此 c1 被提升为 int,除非真正古怪的架构要求提升 charunsigned int。然后对 + 的计算进行求值,并将 int/unsigned int 类型的结果转换回 char 并存储在 c.

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

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

    然后 char 被提升为 intunsigned int,如果它被提升为 int,则 CHAR_MAX + 1 必然适合int 也不会溢出,或者如果 unsigned int 它可能适合或环绕为零。当结果值(在数值上为 CHAR_MAX + 10 在模数减少后返回 c 时,在模数减少后它将变为 0,即 CHAR_MIN

  • 否则char是有符号的,那么如果CHAR_MAX小于INT_MAXCHAR_MAX + 1的结果将适合一个int,并且标准 C11/C18 6.3.1.3p3 适用于发生在 赋值 :

    上的转换
    1. Otherwise, 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.
  • 或者,iff​​sizeof (int) == 1char是有符号的,则char 被提升为 int,并且 CHAR_MAX == INT_MAX => CHAR_MAX + 1 将导致整数溢出并且 行为将是未定义的 .

即可能的结果是:

  • 如果char是无符号整数类型,结果总是0,即CHAR_MIN.

  • 否则char为有符号整数类型,行为为implementation-defined/undefined:

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

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