[英]Detecting overflow for integer in C
#include <stdio.h>
int reverse(int);
int reverse(int x) {
int negative = 0;
if (x < 0)
negative = x;
if (negative != 0) {
x = 0 - x;
}
int y = 0, temp;
while (x > 0) {
temp = x % 10;
x = x / 10;
y = (y * 10) + temp;
}
if (negative == 0) {
return y;
} else {
return 0 - y;
}
}
int main() {
int x, y;
printf("Enter your number: \n");
scanf("%d", &x);
y = reverse(x);
printf("The reversed number is: %d\n", y);
return 0;
}
該程序反轉一個有符號整數。 我無法檢查受尊敬的整數y是否超出范圍。 我無法在溢出主題上弄清楚。 如果我要求編譯器使用scanf掃描整數並輸入超出整數范圍的整數,會發生什么? 值在存儲時會發生變化嗎?
您似乎對溢出有兩個不同的問題。
答案如下。
y <= INT_MAX / 10
,則可以確保y * 10
不會溢出。 關於... + temp
同樣的事情。 scanf
和朋友沒有任何方法可以防止溢出(但是,如果您正在讀取小數,則不能將范圍限制為INT_MAX
)。 如果掃描的值不適合目標類型,則行為未定義。 安全地轉換確切范圍的字符串的唯一方法是與strtol
和friends。 這些函數檢測溢出並相應地設置errno
。 在標准C中,溢出是一種例外情況 ,因此每個標准都不確定行為。 從N11570草案C11 6.5表達式第5節:
如果在表達式的求值過程中出現異常情況(即,如果結果沒有在數學上定義或不在其類型的可表示值范圍內),則行為不確定。
這意味着您不能以按標准定義的方式處理溢出。 話雖這么說,大多數編譯器只是保留結果的低階位以適合類型表示,而忽略最高階位。 這就是MSVC,gcc和clang所做的。
從現在開始,我將假設您的系統對已簽名的int使用int32_t
(分別為int16_t
或int64_t
),並且忽略了溢出。 它不是每個標准都必須執行的,但是很常見,這可能是您的系統所執行的。
您的代碼中可能有2次溢出。 首先是scanf
函數:如@nm所言,如果輸入序列不適合該類型,則此函數族的行為沒有任何說明。 我將假定提交的數字可以作為帶符號的int接受(介於INT_MIN和INT_MAX之間)。 無論如何,讓用戶檢測到它是微不足道的:僅顯示x
:如果它不是剛剛鍵入的數字,則發生溢出。
第二個在這里:
y = (y * 10) + temp;
同樣,通過執行反向操作並控制一切都很好,可以很容易地測試是否有溢出:
int next = (y * 10) + temp;
if ((next < 0) || (y != (next - temp) / 10)) {
// an overflow occured...
...
從理論上講,沒有什么可以保證否定一個正整數是一個有效的負整數,但這對於intXX_t
類型是正確的,因此應該足以檢測到reverse
函數中的溢出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.