【问题标题】:C Manipulating Unsigned Ints - Integer OverflowC操作无符号整数 - 整数溢出
【发布时间】:2014-12-09 19:03:00
【问题描述】:

我正在简单的 C 程序中试验 unsigned int 数据类型和主要方法参数。作为一个实验,我编写了一个程序,它从命令行获取一个 int 数字作为 main 方法的参数,并将该数字与 0 之间的每个整数相加。

例如程序计算 f(n) = (1 + 2 + 3... + n) 当 n > 0 时有效

#include <stdio.h>
#include <stdlib.h>

const unsigned int MAX_NUM = 92681; //Max input that will avoid int overflow later on

unsigned int sum(unsigned int x); 

int main(int argc, char *argv[]) { 

    unsigned int input = atoi(argv[1]); 

    if (input < 0 || input > MAX_NUM) {
        printf("Invalid input! Input must be less than 92682\n");
        exit(0); //If input > MAX_NUM, quit program
    }

    unsigned int result = sum(input);

    printf("Sum to %d = %d\n", input, result);

    return 0;
}

unsigned int sum(unsigned int x) {
    unsigned int sum = 0;
    unsigned int y;
    for (y = 0; y <= x; y++) {
        sum += y;
        printf("Current sum:\t%u\n",sum);
    }
    return sum;
}

我开始注意到的第一件事是当 f(n) > 2147483648 时整数溢出 - 也就是带符号整数的最大值。

我手动找到了我的程序生成的结果有效的最大值(例如,在整数溢出之前)对于有符号整数为 65535,对于无符号整数为 92681。

为有符号整数运行程序产生了预期的结果 - 在 65535 处,由于整数溢出,非常大的正数变成了非常大的负数。

然后我将每个“int”更改为“unsigned int”。尽管发生了整数溢出,就好像整数是有符号的而不是无符号的。

我的问题是 a) 为什么会这样? b)我怎样才能使我的答案可以使用整个无符号整数范围,即从 0 到 (2^32) - 1(因为我不需要负值!)。

非常感谢!

【问题讨论】:

  • 高斯提示:n*(n-1)/2.
  • 这就是我计算最大值的方式,即。 2^32 = n*(n-1)/2

标签: c int integer-overflow atoi unsigned-integer


【解决方案1】:

您忘记将最终的 printf 格式从有符号更改为无符号。

变化:

printf("Sum to %d = %d\n", input, result);

到:

printf("Sum to %u = %u\n", input, result);
               ^^   ^^

请注意,启用编译器警告(例如gcc -Wall ...)会提醒您注意这一点。始终启用编译器警告并始终注意它们。

【讨论】:

  • 好吧,如果这教你始终启用编译器警告,那么这将是值得的。 ;-)
  • @PaulR 不确定 OP 使用的是什么,但我希望 MSVC 最终会开始为此发出警告.../analyze 有点,但速度非常慢,并且没有警告这种特殊情况(签名/无符号不匹配)。哦,好吧,至少我们最终会在“14”版本中获得 C99 (sn)printf,叹息... ;)
  • @user2802841:我没有意识到 MSVC 在这方面仍然落后,尽管我想我不应该感到惊讶 - 大多数其他编译器多年来一直在为 printf 等生成警告当然。
  • @user2802841:为了使此类 printf 警告有用,它们应该考虑到参数是如何产生的。如果u 是unsigned char 类型,则需要在printf 中强制转换(unsigned) 是愚蠢的迂腐,特别是因为没有理由为什么非钝化实现在处理有符号和无符号类型时不会互换处理都在两者的范围内。
猜你喜欢
  • 2013-04-10
  • 2012-02-29
  • 2021-03-15
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
相关资源
最近更新 更多