簡體   English   中英

檢測C中整數的溢出

[英]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掃描整數並輸入超出整數范圍的整數,會發生什么? 值在存儲時會發生變化嗎?

您似乎對溢出有兩個不同的問題。

  1. 如何檢測整數運算中的溢出?
  2. 如何在scanf等轉換函數中檢測ovetflow?

答案如下。

  1. 沒有通用的方法,您必須根據具體情況進行操作。 例如,如果y <= INT_MAX / 10 ,則可以確保y * 10不會溢出。 關於... + temp同樣的事情。
  2. 除了限制字段寬度和輸入范圍外, scanf和朋友沒有任何方法可以防止溢出(但是,如果您正在讀取小數,則不能將范圍限制為INT_MAX )。 如果掃描的值不適合目標類型,則行為未定義。 安全地轉換確切范圍的字符串的唯一方法是與strtol和friends。 這些函數檢測溢出並相應地設置errno

在標准C中,溢出是一種例外情況 ,因此每個標准都不確定行為。 從N11570草案C11 6.5表達式第5節:

如果在表達式的求值過程中出現異常情況(即,如果結果沒有在數學上定義或不在其類型的可表示值范圍內),則行為不確定。

這意味着您不能以按標准定義的方式處理溢出。 話雖這么說,大多數編譯器只是保留結果的低階位以適合類型表示,而忽略最高階位。 這就是MSVC,gcc和clang所做的。

從現在開始,我將假設您的系統對已簽名的int使用int32_t (分別為int16_tint64_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM