设置为 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:
- 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
中会发生什么。这里 +
的操作数经过通常的算术转换,因此 c
和 1
被提升为 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 + 1
或 0
在模数减少后返回 c
时,在模数减少后它将变为 0,即 CHAR_MIN
否则char
是有符号的,那么如果CHAR_MAX
小于INT_MAX
,CHAR_MAX + 1
的结果将适合一个int
,并且标准 C11/C18 6.3.1.3p3 适用于发生在 赋值 :
上的转换
- 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.
或者,iffsizeof (int) == 1
和char
是有符号的,则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 + 1
、c += 1
、c++
和 ++c
在同一平台上具有相同的副作用。表达式 c++
的计算值将是增量前 c
的值;对于其他三个,它将是增量后c
的值。
我的代码:
#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:
- A compound assignment of the form
E1 op = E2
is equivalent to the simple assignment expressionE1 = E1 op (E2)
except that the lvalueE1
is evaluated only once, and with respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. IfE1
has an atomic type, compound assignment is a read-modify-write operation withmemory_order_seq_cst
memory order semantics. 113)
那么,问题是c = c + 1
中会发生什么。这里 +
的操作数经过通常的算术转换,因此 c
和 1
被提升为 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 + 1
或0
在模数减少后返回c
时,在模数减少后它将变为 0,即CHAR_MIN
否则
上的转换char
是有符号的,那么如果CHAR_MAX
小于INT_MAX
,CHAR_MAX + 1
的结果将适合一个int
,并且标准 C11/C18 6.3.1.3p3 适用于发生在 赋值 :- 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) == 1
和char
是有符号的,则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 + 1
、c += 1
、c++
和 ++c
在同一平台上具有相同的副作用。表达式 c++
的计算值将是增量前 c
的值;对于其他三个,它将是增量后c
的值。