什么时候整数宽度受限制?

时间:2015-02-08 05:26:10

标签: c integer 64-bit overflow 32-bit

我在编写一个程序时遇到问题,该程序要求用户输入值N,然后输出结果5 ^ N.问题是,如果用户输入的数字大于(2 ^ 31)-1,他们的号码就会溢出,程序会给他们一个错误的答案。

我所做的是将用户给出的整数值赋给无符号长整数值。这样,如果程序可以检查是否输入了大于(2 ^ 31)-1的数字,因为无符号长整数可以保存比signed int可以多得多的正整数。这样做会导致程序正常运行,因为我可以检查是否发生了溢出。

然而我的问题是这样的:当用户将一个大于2 ^ 31 - 1的值输入到原始有符号整数变量(这会导致它溢出)时,为什么我可以将这个溢出的值分配给一个未签名并得到“正确”的数字是什么?只有在尝试对该号码进行操作时才会发生溢出吗?内存是否存储实际数字(不受位宽限制)?

 int endCount;
unsigned long endCountUn;  /* power N */

/* Read value of N */
printf("This program will compute 5^N; enter N: ");
scanf("%d", &endCount);

/*
User's value put into unsigned long. Helps with detecting overflow.
*/
endCountUn = endCount;

if ( (endCount < 0) && (endCountUn < 2147483648) )
{
    printf("The operation is undefined for negative integers\n");
}

else if ( endCountUn > 2147483647 )
{
    printf("The value exceeds the supported numerical range\n");
}

1 个答案:

答案 0 :(得分:1)

if ( (endCount < 0) && (endCountUn < 2147483648) )

对满足两个条件的数字n执行此if的块。 endCount,是一个(32位)有符号整数,以2的补码表示。 因此,表达式的第一项选择设置高位的所有n:
范围1:[0x80000000 ... 0xFFFFFFFF]
第二项选择范围为
的所有n 范围2:[0x00000000..0x7FFFFFFF]。
两个范围内的n的集合是空集。 所以,你上面的身体永远不会被执行。

第二个if(否则为部分)请求范围1中的值。

因此,您的测试代码可以简化为:

if( endCount < 0 ) { printf("Value out of range"); }

因为,无论用户输入什么(范围1中的负数或值),endCount将始终为负数。

最后,如果您只想允许无符号整数值,为什么首先使用scanf("%d",endCount)
你可以写一下:

uint32_t endCount = 0; // unsigned int is machine dependent...better use stdint.h...
...
scanf("%u", &endCount);

声明的输出,用于产生第二个printf ...

This program will compute 5^N; enter N: 2147483648
The value exceeds the supported numerical range

声明的输出,用于产生第一个printf ...

This program will compute 5^N; enter N: -10
The value exceeds the supported numerical range

请查看此程序在您的系统上输出的内容......

uint32_t endCount;

/* Read value of N */
printf("This program will compute 5^N; enter N: ");
scanf("%u", &endCount);

printf("entered value = %d (as signed)\n",endCount);
printf("entered value = %u (as unsigned)\n",endCount);

在我的系统上:

This program will compute 5^N; enter N: -10
entered value = -10 (as signed)
entered value = 4294967286 (as unsigned)