我的代码:
#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或 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.
sizeof (int) == 1
和 char
签名,然后 char
被提升为 int
, 和 CHAR_MAX == INT_MAX
=> CHAR_MAX + 1
将导致整数溢出和 行为将是未定义的 . IE。可能的结果是:
char
是无符号整数类型,结果总是0
,即 CHAR_MIN
. char
是有符号整数类型,行为是实现定义的/未定义的:CHAR_MIN
或其他一些实现定义的值,sizeof (char) == sizeof (int)
. 所有增量操作
c = c + 1
, c += 1
, c++
和 ++c
在同一平台上有相同的副作用。表达式 c++
的计算值将是 c
的值增量前;对于其他三个,它将是 c
的值增量后。
关于c - 设置为 CHAR_MAX 的字符值是否保证环绕到 CHAR_MIN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60586881/