12個有趣的C語言問答_sunyrising-ChinaUnix博客

http://www.oschina.net/question/213217_69069
1,gets() 方法Q:以下代碼有個被隱藏住的問題,你能找到它嗎?01#include0203intmain(void)04{05charbuff[10];06memset(buff,0,sizeof(buff));0708gets(buff);0910printf("\n The buffer entered is [%s]\n",buff);1112return0;13}


A:這個不顯眼的問題就是使用了 gets() 方法。此方法接受一個string類型參數,但是卻沒有檢測此數值是否有足夠的空間來拷貝數據。所以這裏我們一般用 fgets() 方法將來的更好。
2,strcpy() 方法Q:密碼防護是很基本的功能,看看能否搞定下面這段代碼?01#include0203intmain(intargc,char*argv[])04{05intflag = 0;06charpasswd[10];0708memset(passwd,0,sizeof(passwd));0910strcpy(passwd, argv[1]);1112if(0 ==strcmp("LinuxGeek", passwd))13{14flag = 1;15}1617if(flag)18{19printf("\n Password cracked \n");20}21else22{23printf("\n Incorrect passwd \n");2425}26return0;27}


3,main() 方法的返回類型Q:請問下面這段代碼能否通過編譯?如果能的話,那麼這段代碼中隱含什麼問題嗎?01#include0203voidmain(void)04{05char*ptr = (char*)malloc(10);0607if(NULL == ptr)08{09printf("\n Malloc failed \n");10return;11}12else13{14// Do some processing1516free(ptr);17}1819return;20}


A:答案是代碼能通過編譯,但是會留下針對main()方法的返回類型的警告。main()方法的真正返回類型應該爲'int'而非'void'。這是因爲'int'返回類型能夠讓程序返回狀態值。尤其是當這段程序作爲其他應用的附屬程序時這個狀態值將更加重要。

4,內存泄露Q:請問以下代碼有內存泄露嗎?01#include0203voidmain(void)04{05char*ptr = (char*)malloc(10);0607if(NULL == ptr)08{09printf("\n Malloc failed \n");10return;11}12else13{14// Do some processing15}1617return;18}


A:好,雖然上面的代碼沒有對指針 ptr 進行內存釋放,但實際上即使是程序結束也不會造成內存泄露,因爲當程序結束時所有一開始被佔據的內存就全部清空了。但如果上面這段代碼是在 while 循環裏面那將會造成嚴重的問題。

Note: 如果你需要了解更多關於內存泄露的問題以及如何使用工具檢測內存泄露,你可以參考這篇文章Valgrind
5,free() 方法Q:以下代碼當用戶輸入'freeze'時會奔潰,而如果輸入'zebra'則運行正常,這是爲什麼?01#include0203intmain(intargc,char*argv[])04{05char*ptr = (char*)malloc(10);0607if(NULL == ptr)08{09printf("\n Malloc failed \n");10return-1;11}12elseif(argc == 1)13{14printf("\n Usage \n");15}16else17{18memset(ptr, 0, 10);1920strncpy(ptr, argv[1], 9);2122while(*ptr !='z')23{24if(*ptr =='')25break;26else27ptr ;28}2930if(*ptr =='z')31{32printf("\n String contains 'z'\n");33// Do some more processing34}3536free(ptr);37}3839return0;40}


A:問題的根源是因爲代碼在while循環中改變了 ptr 指針的地址。當輸入爲'zebra'時,while循環甚至在執行第一遍前就結束了,所以free()釋放的內存地址就是一開始malloc()分配的地址。但是當輸入'freeze'時,ptr記錄的地址在while循環中被更改,因爲將會是錯誤的地址傳遞到free()方法中引起崩潰。
6,atexit with _exitQ:在以下代碼,atexit()方法並沒有被調用,你知道爲什麼嗎?01#include0203voidfunc(void)04{05printf("\n Cleanup function called \n");06return;07}0809intmain(void)10{11inti = 0;1213atexit(func);1415for(;i<0xffffff;i );1617_exit(0);18}


A:這是因爲使用了 _exit() 方法。此方法並沒有調用清除數據相關的方法,比如 atexit()等。
7,void* 與 C 結構體Q:能否設計一個方法接受任意類型的參數然後返回整數?同時是否有辦法傳遞多個這樣的參數?A:一個能接受任意類型參數的方法像下面這個樣子:1intfunc(void*ptr)


如果需要傳遞多個參數,那麼我們可以傳遞一個包含這些參數的結構體
8,* 與 操作符Q:以下代碼將輸出什麼?爲什麼?01#include0203intmain(void)04{05char*ptr ="Linux";06printf("\n [%c] \n",*ptr );07printf("\n [%c] \n",*ptr);0809return0;10}


A:以上的輸出將是:1[L]23[i]


因爲 與 * 的優先級一樣,所以 *ptr 將會從右向左操作。按照這個邏輯,ptr 會先執行然後執行*ptr。所以第一個結果是'L'。也因爲 被執行了,所以下一個printf() 結果是'i'。
9,Making changes in Code segmentQ:以下代碼運行時一定會崩潰,你能說出原因嗎?01#include0203intmain(void)04{05char*ptr ="Linux";06*ptr ='T';0708printf("\n [%s] \n", ptr);0910return0;11}


A:這是因爲,通過 *ptr = 'T',此行代碼嘗試更改只讀內存存儲的字符串'Linux'。此操作當然行不通所以纔會造成崩潰。
10,Process that changes its own nameQ:你能否寫一個程序在它運行時修改它的名稱?A:以下代碼可以完成01#include0203intmain(intargc,char*argv[])04{05inti = 0;06charbuff[100];0708memset(buff,0,sizeof(buff));0910strncpy(buff, argv[0],sizeof(buff));11memset(argv[0],0,strlen(buff));1213strncpy(argv[0],"NewName", 7);1415// Simulate a wait. Check the process16// name at this point.17for(;i<0xffffffff;i );1819return0;20}



11,局部變量的返回地址Q:下面的代碼有問題嗎?如果有,如何修改?01#include0203int* inc(intval)04{05inta = val;06a ;07returna;08}0910intmain(void)11{12inta = 10;1314int*val = inc(a);1516printf("\n Incremented value is equal to [%d] \n", *val);1718return0;19}


A:雖然上面的代碼有時運行會很好,但是在方法 inc() 中有很嚴重的隱患。當inc()方法執行後,再次使用局部變量的地址就會造成不可估量的結果。解決之道就是傳遞變量a的地址給main()。
12,處理 printf() 參數Q:以下代碼輸出請問是什麼?view sourceprint?01#include0203intmain(void)04{05inta = 10, b = 20, c = 30;0607printf("\n %d..%d..%d \n", a b c, (b = b*2), (c = c*2));0809return0;10}


A:輸出將是1110..40..60


這是因爲參數都是從右向左處理的,然後打印出來卻是從左向右。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章