【问题标题】:Integer overflow happening with unsigned variables无符号变量发生整数溢出
【发布时间】:2019-08-18 02:59:54
【问题描述】:

我试图对 C 进行 100 的阶乘运算,结果发生了整数溢出,但我不明白为什么我的无符号变量变为负数。

int main(void)
{
    unsigned long value =1;
    for(unsigned long n = 0;n<100;n++){
        printf("This n %ld\n",value);
        value *= (n+1);
    }
    printf("%ld\n",value);
    return 0;
}

对于无符号变量,变量容量溢出后,不应该重新从0开始吗?

value的第一个值:

This current value 2  
This current value 6  
This current value 24  
This current value 120  
This current value 720  
This current value 5040  
This current value 40320  
This current value 362880  
This current value 3628800  
This current value 39916800  
This current value 479001600  
This current value 6227020800  
This current value 87178291200  
This current value 1307674368000  
This current value 20922789888000  
This current value 355687428096000  
This current value 6402373705728000  
This current value 121645100408832000  
This current value 2432902008176640000  
This current value -4249290049419214848

这怎么可能?

【问题讨论】:

  • 你对printf() 撒了谎——你说你传递了一个(签名的)long,所以它听了你的话并打印了位模式,就好像它代表一个签名的long,并且该位模式被解释为负数。更改为%lu 并要求它以十进制打印unsigned long。 (是的:无符号变量环绕并在零处重新启动。)

标签: c unsigned integer-overflow


【解决方案1】:

%ld in printf 会将任何数字解释为已签名的数字。每个数字都可以读取为有符号或无符号。要打印您的未签名只要未签名,您应该将%lu 传递给printf。

无符号数和有符号数之间的区别在于编译器在处理此变量时将选择使用哪些汇编指令。在汇编级别,有一组指令旨在处理应该是有符号数的指令集和其他指令集来处理无符号数(例如,当您通过if 语句检查变量的值时,如果它被声明为有符号编译器将生成一些指令,如果不是,编译器将生成其他指令)。 char c = -1 和 unsigned char c = 255 在内存中存储为完全相同的值。

【讨论】:

  • 第二段的错误比瑞士奶酪的洞还多。最重要的是,char c = -1 和 unsigned char c = 255 的值在 x86 上不同,其中 char 已签名 - 一个是 -1,一个是 255。在 ARM 上它们是相同的,因为两者都是 255。如果你指的是表示中的位,那么这是实现定义的,取决于 char 的大小和带符号的表示(如果有)。 CPU 标志与有符号整数溢出的未定义行为无关。
  • @AnttiHaapala 您能否详细说明一下 -1 在 x86 上与 255 不同(考虑到我说的是当您将 -1 设置为 signed char 和255 到unsigned char)?关于你的第二个论点,我完全不明白。关于 CPU 标志,我说的是程序如何处理信号。这一切都由编译器处理,因为如果变量是有符号或无符号的,编译器将创建正确的指令集 - 在汇编级别没有符号变量,这完全取决于您将使用哪些指令。
  • 忘掉处理器吧。 -1 是 -1 和 255 是 255,这些是变量的值。
  • @AnttiHaapala 如果我的论点围绕这些值如何存储在内存中并由处理器处理,我为什么要忘记处理器?
  • 好吧,我更新了文字,试图更清楚地说明我在说什么,请检查你现在是否可以接受@AnttiHaapala
猜你喜欢
  • 2012-02-29
  • 2013-04-10
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 2016-03-01
  • 2021-03-28
  • 2021-03-15
  • 1970-01-01
相关资源
最近更新 更多