我在编写一个程序时遇到问题,该程序要求用户输入值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");
}
答案 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)