无符号溢出在C模运算符 [英] unsigned overflow with modulus operator in C
问题描述
我遇到了一些C code我写了一个错误,而这是比较容易解决,我希望能够更好地理解它背后的问题。本质上发生了什么事是我有两个无符号整数(uint32_t的,其实),当应用于模操作,得到一个负数,已被包裹了一些未签名等同,是这样的大。下面是一个例子程序来演示:
i encountered a bug in some c code i wrote, and while it was relatively easy to fix, i want to be able to understand the issue underlying it better. essentially what happened is i had two unsigned integers (uint32_t, in fact) that, when the modulus operation was applied, yielded the unsigned equivalent of a negative number, a number that had been wrapped and was thus "big". here is an example program to demonstrate:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char* argv[]) {
uint32_t foo = -1;
uint32_t u = 2048;
uint64_t ul = 2048;
fprintf(stderr, "%d\n", foo);
fprintf(stderr, "%u\n", foo);
fprintf(stderr, "%lu\n", ((foo * 2600000000) % u));
fprintf(stderr, "%ld\n", ((foo * 2600000000) % u));
fprintf(stderr, "%lu\n", ((foo * 2600000000) % ul));
fprintf(stderr, "%lu\n", foo % ul);
return 0;
}
这将产生以下输出,我x86_64的机器上:
this produces the following output, on my x86_64 machine:
-1
4294967295
18446744073709551104
-512
1536
2047
1536年是我期待的数目,但(uint32_t的)( - 512)是我渐渐,其数量,如你所想,扔东西了,有点
1536 is the number i was expecting, but (uint32_t)(-512) is the number i was getting, which, as you might imagine, threw things off a bit.
所以,我想我的问题是:为什么两个无符号数之间的模运算,在这种情况下,生产出一批比除数(即负数)更大?是有这种行为preferred理由吗?
so, i guess my question is this: why does a modulus operation between two unsigned numbers, in this case, produce a number that is greater than the divisor (i.e. a negative number)? is there a reason this behavior is preferred?
推荐答案
我想原因是编译器是跨preting的 26亿
文本作为签约64位的数目,因为它不适合成为一个符号的32位int。如果换成 2600000000U
的数量,你应该得到你所期望的结果。
I think the reason is that the compiler is interpreting the 2600000000
literal as a signed 64-bit number, since it does not fit into a signed 32-bit int. If you replace the number with 2600000000U
, you should get the result you expect.
这篇关于无符号溢出在C模运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!