我在編寫一個程序時遇到了麻煩,該程序要求用戶輸入一個值N,然後輸出結果5^N。問題是,如果用戶輸入了一個大於(2^31)-1的數字,他們的數字就會溢出,程序會給他們一個錯誤的答案。何時限制整數寬度?
我所做的是將用戶給定的整數值賦給一個無符號的長整數值。這樣,如果程序可以檢查是否輸入了大於(2^31)-1的數字,因爲無符號long可以保存比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");
}
在C,整數不會 「溢出」。您可以將其視爲模操作,其中某些操作的結果總是以「模2 ^(位)」進行處理。就像你寫的表達式附加了一個看不見的部分。簽名整數通常以2的補碼錶示。你的測試在你的第一個基本測試,如果上面 - 你的數字的符號位是1(這意味着否定的,如果它被解釋爲一個有符號的值)。所以你所需要了解的是查看2的補碼是如何工作的。 – BitTickler 2015-02-08 05:35:34
@ user2225104:無符號整數不會溢出;它們將模2^N包裹,其中N是位數。另一方面,當有符號整數溢出時,會觸發未定義的行爲,並且可能發生任何事情(包括代碼似乎通過從正向轉爲負向工作)。未定義的行爲是未定義的。 – 2015-02-08 07:30:01
請注意,當scanf()被要求處理的數字太大而不適合整數類型時,scanf()的行爲是不確定的。如果在32位有符號類型中輸入大於2^31-1的值,則得到的結果未定義。通常會發生什麼,但從形式上講,行爲是不確定的。 (ISO 9899:2011§7.21.6.2'fscanf'函數¶10表示_'...或者如果對象中的轉換結果不能表示爲 ,則行爲是未定義的。'_ – 2015-02-08 07:32:14