1、前言
最近在網上看到一道C語言題目, 用C語言實現一個函數, 給定一個int類型的整數, 函數輸出逆序的整數, 例如輸入123, 則輸出字串"321",, 輸入-123, 則輸出字串"-321"。 題目要求, 不使用標準庫, 不得分配記憶體。 當時覺得蠻簡單的, 這不就是類似字串逆轉嘛, 自己嘗試做了一下, 測試發現, 還是有很多地方考慮不周全。 今天在此整理一下基礎知識, 作為一名安全開發人員, 時刻需要注意代碼的安全, 防止有任何漏洞。 題目給出的函數如下:
#include const char * parseInt(int data) { return "321"; } int main { printf("%s ", parseInt(123)); return 0; }2、思考過程
寫代碼最怕的就是沒有想好, 一上來就寫, 在寫的過程中不斷的測試修改,
(1)int類型的整數分為正數、0、負數, 如何處理這些邊界值
(2)整數與字串之間的轉換, 如何將一個整數轉換為一個字元
(3)如何返回一個const char * 類型的字串
(4)當輸入的整數超過int的範圍如何處理
3、編碼過程
開始寫代碼的思路如下:定義一個char類型的陣列, 用於保存結果。 使用對10取餘和除法操作依次獲取每一位元的數位, 然後根據ASSIC碼轉換為字元。 將字元拼接起來, 返回字串陣列結果。 編碼實現如下:
const char * parseInt(int data) { char str[16] = {0}; int i = 0; if (data當初沒有考慮那麼多, 編譯發現出現如下錯誤:
一看編譯錯誤, 才意識到自己掉入坑中。 題目要求返回一個字串, 而且不用分配記憶體。 當時就想直接定義一個字元陣列進行返回,
一個函數的區域變數都是存在stack中的, 當這個函式呼叫過程結束時, 這個區域變數都是要釋放掉的, 所以就會產生這樣的warning, 這個是和變數的life time相關的, 所以解決方法有:
1.將char result[16]改為static型
2.使用malloc向heap申請, 這些是需要caller用free去釋放的
於是使用static 類型字串, 代碼改進如下:
1 const char * parseInt(int data) 2 { 3 static char str[16] = {0}; 4 int i = 0; 5 6 if (dataint main
{
printf("%s ", parseInt(123));
printf("%s ", parseInt(12345678));
printf("%s ", parseInt(-89790));
return 0;
}
測試結果如下:
改為static之後, 編譯成功, 看輸出的結果上看, 前面兩個輸出是正確的, 而第三個輸出的結果是錯誤的。 尼瑪, 再次掉入坑中, 對static變數的應用不精通啊。 為什麼每次到看到結果後才想起來?
雖然在函數中定義了static區域變數, 使得變數的變為靜態stack存儲區域, 生命週期從函數中變成了這個程式的範圍。 但是static區域變數在函數第一次調用的時候會初始化,
static靜態區域變數屬於靜態存儲方式, 它具有以下特點:
(1)靜態區域變數在函數內定義 它的生存期為整個來源程式, 但是其作用域仍與自動變數相同, 只能在定義該變數的函數內使用該變數。 退出該函數後, 儘管該變數還繼續存在, 但不能使用它。
(2)允許對構造類靜態局部量賦初值 例如陣列, 若未賦以初值, 則由系統自動賦以0值。
(3)對基本類型的靜態區域變數若在說明時未賦以初值, 則系統自動賦予0值。 而對自動變數不賦初值, 則其值是不定的。 根據靜態區域變數的特點, 可以 看出它是一種生存期為整個來源程式的量。
第一次調用函數, static變數, 初始化。 第二次, 及以後, 調用函數, static變數, 不會初始化。
繼續改進代碼, 在函數中將static變數每次使用for迴圈進行初始化, 改進代碼如下:
1 #include 2 3 const char * parseInt(int data) 4 { 5 static char str[16] = {0}; 6 int i = 0; 7 8 int t = 0; 9 for (; t這次輸出結果如下:
終於得到了正確答案, 看似很簡單的題目, 折騰的這麼久, 才搞出來。 擴展一下, 大家看看如下這個輸出什麼呢:
printf("%s, %s, %s ", parseInt(98989),parseInt(-4567), parseInt(123456));這個結果是什麼呢?為什麼會這樣呢?
printf("%s ", parseInt(0xFFFFFFFF));
這個結果是什麼呢?為什麼會這樣呢?
int 類型4個位元組, 32位元組成。 int的最高位元作為符號位元, 需要特殊處理。