程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 那個你經常用的abs函數(取絕對值)真的總是返回非負數嗎?,abs絕對值

那個你經常用的abs函數(取絕對值)真的總是返回非負數嗎?,abs絕對值

編輯:C++入門知識

那個你經常用的abs函數(取絕對值)真的總是返回非負數嗎?,abs絕對值


  前幾天在牛客網看到一道關於abs()函數返回值的題目,見下圖,當時還沒反應過來,第一反應是:自從我開始學C語言,就知道它是用來求int數的絕對值的,返回值當然是0或者正數啊,一看答案就是A。

  後來思來想去,質問自己 難道這道題就這麼簡單?於是果斷先查函數庫,得到:

#include <stdlib.h> //或math.h
int abs( int num );

  發現庫函數的返回值形式都寫的是int,為什麼是int?經過深入的思考、驗證和查閱資料,最後得出:

當num為0或正數時,函數返回num值;
當num為負數且不是最小的負數時(即0x80000000),函數返回num的對應絕對值數,即將內存中該二進制位的符號位取反,並把後面數值位取反加一;
當num為最小的負數時,由於正數裡int類型32位表示不了這個數的絕對值,所以依然返回該負數。
  貼上代碼運行結果:          也就是說,對於普通程序員來說,直接用abs來求一個數的絕對值並沒有想象中那麼安全,如果恰好給它傳遞了一個最小的負數作為參數,得到的依然是這個負數,而不是它的絕對值,也許後面將會發生各種意想不到的情況。因此,每一位程序員都應該明白:調用函數後檢查函數返回值是一個優秀程序員應該具備的基本素養。   “經常反問:這個變量或表達式會上溢或下溢嗎?”(《編程精粹-Microsoft編寫優質無錯C程序秘訣》P80,Steve Maguire 著)     引用一段來自一個博客的話作為結束:
ANSI C標准規定了每種整數類型的最小值域(但沒有規定它們必須采用哪種編碼方案),並要求所有的C語言實現都要在limits.h頭文件中通過諸如INT_MIN、INT_MAX這樣的宏來指定該實現中整型數據的實際值域,而且這些實際的值域一定不能比標准規定的最小值域還要小(也即要求每種實現在limits.h中定義的宏的絕對值不小於C標准規定的同名宏的絕對值,並且正負號要保持一致)。
標准定義的INT_MIN是-(2^15 - 1),INT_MAX是(2^15 - 1),換句話說,標准保證了int型數據至少能表示-(2^15 - 1)到(2^15 - 1)這樣一個對稱區間內的所有整數,因此程序員可以放心大膽地用int變量存儲以上范圍內的任何整數。但與此同時請特別注意,用int變量表達超出上述范圍的數將是一件沒有法律(標准即是程序員的法律)保障的事情,所以不應該想當然地認為-32768(即-2^15)一定可以用int型來表達,盡管它確實位於用二次補碼記法(twos-complement notation)進行編碼的16位整數的值域內。熟悉以上背景後再回顧abs函數的問題就會發現,實際上該函數對於標准規定范最小值域內的所有整數都能正常工作,而上面提到的引起錯誤的輸入數據已經不在此范圍內了,所以此錯誤不應由abs而應由函數調用者負責。由此可見,為了安全以及可移植性,將表達式欲表示的值嚴格限制在標准指定的最小值域內是一個良好的編程習慣。
   參考:   function abs ——cplusplus.com   C標准庫函數abs的一個錯誤   [單選題]math.h的abs返回值()

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved