avm*_*han 25 c overflow modulo integer-arithmetic
我需要在C中进行模256运算.所以我可以简单地做
unsigned char i;
i++;
Run Code Online (Sandbox Code Playgroud)
代替
int i;
i=(i+1)%256;
Run Code Online (Sandbox Code Playgroud)
Ale*_* C. 25
没有.没有什么可以保证unsigned char有八位.使用uint8_t从<stdint.h>,你会完全恢复健康的.这需要一个支持的实现stdint.h:任何符合C99的编译器都可以,但是较旧的编译器可能不提供它.
注意:无符号算术永远不会溢出,并且表现为"modulo 2 ^ n".带有未定义行为的带符号算术溢出.
是的,两个示例的行为都是相同的.见C996.2.5§9:
涉及无符号操作数的计算永远不会溢出,因为无法通过生成的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数量为模.
很可能是,但是在这种情况下这样做的原因实际上相当复杂。
unsigned char i = 255;
i++;
Run Code Online (Sandbox Code Playgroud)
在i++相当于i = i + 1。
(好吧,几乎。在递增之前i++产生的值,因此它实际上等于。但是由于在这种情况下结果被丢弃,因此不会引起任何其他问题。)i (tmp=i; i = i + 1; tmp)
由于unsigned char是窄类型,因此将unsigned char运算+符提升为操作数int(假设int可以将所有可能的值保存在的范围内unsigned char)。因此,如果i == 255和UCHAR_MAX == 255,则加法的结果为256,并且类型为(signed)int。
赋值将值256从隐式转换int为unsigned char。转换为无符号类型的定义很明确;结果以模为模MAX+1,其中MAX是目标无符号类型的最大值。
如果i被声明为unsigned int:
unsigned int i = UINT_MAX;
i++;
Run Code Online (Sandbox Code Playgroud)
不会进行类型转换,但是+无符号类型的运算符的语义也指定了缩减模块MAX+1。
请记住,分配给的值在i数学上等于(i+1) % UCHAR_MAX。UCHAR_MAX是通常 255,并且保证是至少 255,但是它可以合法更大。
可能会有一个奇异的系统,该系统UCHAR_MAX也无法存储在一个已签名的int对象中。这将要求UCHAR_MAX > INT_MAX,这意味着系统将必须至少具有 16位字节。在这样的系统上,升级将是从unsigned char到unsigned int。最终结果将是相同的。您不太可能遇到这样的系统。我认为某些字节大于8位的DSP有C实现。字节中的位数由中CHAR_BIT定义<limits.h>。
CHAR_BIT > 8不一定暗示UCHAR_MAX > INT_MAX。例如,您可以拥有CHAR_BIT == 16and(sizeof (int) == 2即16位字节和32位int)。
unsigned char c = UCHAR_MAX;
c++;
Run Code Online (Sandbox Code Playgroud)
基本上是的,没有溢出,但不是因为c是无符号类型.有一个隐藏的推广c到int这里,并从整数转换int到unsigned char,它是完美的定义.
例如,
signed char c = SCHAR_MAX;
c++;
Run Code Online (Sandbox Code Playgroud)
也不是未定义的行为,因为它实际上相当于:
c = (int) c + 1;
Run Code Online (Sandbox Code Playgroud)
和从转换int到signed char由实现定义在这里(见C99,整数转换6.3.1.3p3).CHAR_BIT == 8假设是简化的.
有关上述示例的更多信息,我建议您阅读以下文章:
"来自地狱的小C功能"
http://blog.regehr.org/archives/482