題目:
已知strcpy函式的原型是:
char * strcpy(char * strdest,const char * strsrc);
1.不呼叫庫函式,實現strcpy函式。
2.解釋為什麼要返回char *。
解說:1.strcpy的實現**
錯誤的做法:
[1](a)不檢查指標的有效性,說明答題者不注重**的健壯性。
(b)檢查指標的有效性時使用((!strdest)||(!strsrc))或(!(strdest&&strsrc)),說明答題者對c語言中型別的隱式轉換沒有深刻認識。在本例中char *轉換為bool即是型別隱式轉換,這種功能雖然靈活,但更多的是導致出錯概率增大和維護成本公升高。所以c++專門增加了bool、true、false三個關鍵字以提供更安全的條件表示式。
(c)檢查指標的有效性時使用((strdest==0)||(strsrc==0)),說明答題者不知道使用常量的好處。直接使用字面常量(如本例中的0)會減少程式的可維護性。0雖然簡單,但程式中可能出現很多處對指標的檢查,萬一出現筆誤,編譯器不能發現,生成的程式內含邏輯錯誤,很難排除。而使用null代替0,如果出現拼寫錯誤,編譯器就會檢查出來。
[2](a)return new string("invalid argument(s)"
(b)return 0;,說明答題者沒有掌握異常機制。呼叫者有可能忘記檢查返回值,呼叫者還可能無法檢查返回值(見後面的鏈式表示式)。妄想讓返回值肩負返回正確值和異常值的雙重功能,其結果往往是兩種功能都失效。應該以丟擲異常來代替返回值,這樣可以減輕呼叫者的負擔、使錯誤不會被忽略、增強程式的可維護性。
[3](a)忘記儲存原始的strdest值,說明答題者邏輯思維不嚴密。
[4](a)迴圈寫成while (*strdest++=*strsrc++);,同[1](b)。
(b)迴圈寫成while (*strsrc!='/0') *strdest++=*strsrc++;,說明答題者對邊界條件的檢查不力。迴圈體結束後,strdest字串的末尾沒有正確地加上'/0'。
2.返回strdest的原始值使函式能夠支援鏈式表示式,增加了函式的「附加值」。同樣功能的函式,如果能合理地提高的可用性,自然就更加理想。
鏈式表示式的形式如:
int ilength=strlen(strcpy(stra,strb));
又如:char * stra=strcpy(new char[10],strb);
返回strsrc的原始值是錯誤的。其一,源字串肯定是已知的,返回它沒有意義。其二,不能支援形如第二例的表示式。其三,為了保護源字串,形參用const限定strsrc所指的內容,把const char *作為char *返回,型別不符,編譯報錯。
char * __cdecl strcpy(char * dst, const char * src)
from strcat 的**
微軟的**。 的確是的 strcpy 根本沒有考慮異常, 錯誤,失敗的情況。
套用這裡某位老兄原來的說法 就是讓他直接崩潰,然後找到bug.
但是應該說 你如果面試敢寫 上面的** 就意味著你面試的結束。
可以這樣簡單的總結:對於乙個系統的內部,應該盡可能由呼叫者保證引數的正確性;而對於系統與系統之間的介面,則實現者必須檢查引數的有效性,應該力求作到對於任何輸入,自己都不會crash。strcpy()是前者的乙個例子。對於後一種情況,考慮系統呼叫:無論任何引數,os核心絕對沒理由crash;再有web server的例子,無論瀏覽器向server傳送了多麼不合理的請求,web server都不應該crash
我來補充一點:
記憶體訪問違例,在linux下會導致os給你發乙個sign 11
如果你捕獲了這個sign 11並內建機制妥善處理了它(比如,可以使用setjmp/longjmp,或者乾脆用c++提供的現成品try-catch),那麼程式顯然是不會崩潰的:這是正確且唯一正確的做法。
請用gdb開啟所有因為記憶體訪問違例導致crash的core,你會發現程式崩潰的原因不是因為記憶體訪問違例,而是沒有處理sign 11,從而導致處理流程跑進系統內建的core dump例程之中
sign 11並非唯一可用的手段——如果深入了解過作業系統的話。
如果感覺不能理解的話,請去查查資料,搞明白cpu執行某指令,發現它訪問無效記憶體或除零錯、溢位等等發生後,繼而發生的一切細節。
我們一直強調程式有bug就讓它crash,原因就在於我們有無數的後續手段,可用以保證**總體的穩定。
隱藏錯誤去嚴防crash,** 區域性 看來是穩定了——但 總體 質量必定會是一坨屎。
bjarne stroustrup特意強調在c++裡應當用0,而非null。
5.8 advice [ptr.advice]
[3] use0 rather than n u l l ; §5.1.1.
你看過c的標準嗎?
6.3.2.3 pointers
3 an integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) if a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
55) the macro null is defined in (and other headers) as a null pointer constant; see 7.17.
林銳高質量程式設計中的幾道面試題
目錄 記憶體的思考 在c 程式中呼叫被c 編譯器編譯後的函式為什麼要加extern c 編寫strcpy 函式 編寫類string 的建構函式析構函式和賦值函式 片段1修改方法有三種 方法一 可以在getmemory函式中加上乙個返回開闢空間的指標,通過它再對test函式中的str指標重新賦值,可以...
高質量C 程式設計 測試題
本試題僅用於考查c c程式設計師的基本程式設計技能。內容限於c c常用語法,不涉及資料結構 演算法以及深奧的語法。考試成績能反映出考生的程式設計質量以及對c c的理解程度,但不能反映考生的智力和軟體開發能力。筆試時間90分鐘。請考生認真答題,切勿輕視。一 請填寫bool float,指標變數 與 零...
C 高質量程式設計點滴
摘自 http www.sudu.cn info html edu c 20070103 236588.html 一 你需要乙個函式將乙個陣列賦值為等差數列,並將會在函式的外部使用他。不合理 int getarray int n return p 合理 void getarray int p,int...