繁体   English   中英

C中的模运算符无符号溢出

[英]unsigned overflow with modulus operator in C

我在编写的某些C代码中遇到了一个错误,虽然相对容易修复,但我希望能够更好地理解它的根本问题。 从本质上讲,发生的事情是我有两个无符号整数(实际上是uint32_t),当应用模运算时,该整数产生了一个负数的无符号等效项,该数字已被包装并因此是“大”的。 这是一个示例程序来演示:

#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机器上产生以下输出:

-1
4294967295
18446744073709551104
-512
1536
2047

1536是我期望的数字,但是(uint32_t)(-512)是我得到的数字,正如您可能想像的那样,这使事情有所减少。

因此,我想我的问题是:为什么在这种情况下两个无符号数之间的模运算会产生一个大于除数的数字(即负数)? 有这种行为偏爱的原因吗?

我认为原因是编译器将2600000000文字解释为带符号的64位数字,因为它不适合带符号的32位int。 如果将数字替换为2600000000U ,则应获得期望的结果。

我没有方便的参考,但是我很确定当您执行该乘法时,它会将它们提升为int64_t ,因为它需要将两个被乘数强制转换为有符号整数类型。 尝试使用2600000000u而不是2600000000 ....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM