兩道面試題所引發(fā)的C指針的思考

C語言是一門使用比較廣泛的高級編程語言赢笨,而指針則是C語言的精髓所在,可以說學(xué)習C語言不會靈活使用指針就談不上精通C語言液肌。但是由于C語言指針的靈活性導(dǎo)致了我們在使用過程中出現(xiàn)莫名其妙的各種問題疮鲫,甚至是段錯誤月弛。

本文引用地址:http://www.embedu.org/Column/7260.html

本文將以兩道典型的面試題為切入點,引發(fā)我們對于C語言指針的思考芋浮。并給予詳細的解釋抱环,從原理角度來解析C指針。全文也是源碼分析加結(jié)果演示的形式說明問題所在纸巷。

問題一:

一下的代碼段是否正確镇草,如果正確結(jié)果是什么?如果不正確如何改正?

void fun(char *p)

{

p=(char *)malloc(100);

}

int main(int argc, const char *argv[])

{

char *str=NULL;

fun(str);

strcpy(str,"hello");

printf("%s\n",str);

return 0;

}

如果大家不仔細看的話,一定認為是正確的瘤旨,因為沒有發(fā)現(xiàn)明顯的語法錯誤梯啤。不錯你的想法是對的,編譯的時候一定可以通過存哲,但是當你運行可執(zhí)行程序的時候發(fā)現(xiàn):“哎呀因宇,段錯誤!”,也沒錯祟偷,確實也發(fā)生了段錯誤察滑,也許這個段錯誤比較隱蔽不易發(fā)現(xiàn)并定位。下面我們使用gdb來定位到段錯誤的位置修肠,并分析錯誤原因:

命令行輸入:gcc -g -rdynamic test.c (test.c即是我們將源碼頭文件加上編寫的C語言源文件)贺辰,然后生成了可以以用于gdb調(diào)試且可以定位段錯誤的可執(zhí)行程序,接下來輸入gdb ./a.out 進入gdb調(diào)試模式嵌施,輸入r運行程序饲化,則立馬定位到strcpy(str,"hello"); 這行程序段,于是我們回到程序中分析代碼:發(fā)現(xiàn)是我們把一個指針常量NULL作為fun函數(shù)的參數(shù)傳遞給了p,造成了子函數(shù)中對一個指針常量進行賦值操作吗伤,于是就在程序運行中調(diào)用fun函數(shù)的時候造成了段錯誤滓侍。

以上就是這段代碼的錯誤分析,既然我們通過gdb定位到了段錯誤的位置牲芋,也分析出了段錯誤產(chǎn)生的原因撩笆,那么如何修改代碼才能實現(xiàn)相應(yīng)的功能還不至于造成段錯誤呢?考慮到要盡量保證代碼段的完整性捺球,于是想到從傳遞的參數(shù)上尋突破口。既然不能傳遞指針常量夕冲,那么我們想到傳遞一個值能夠裝得下指針不就行了于是對代碼段做如下改變(修改部分已做好了紅色標記):

void fun(char **p)

{

*p=(char *)malloc(100);

}

int main(int argc, const char *argv[])

{

char *str=NULL;

fun(&str);

strcpy(str,"hello");

printf("%s\n",str);

return 0;

}

對比發(fā)現(xiàn)氮兵,這次我們傳遞了一個二級指針&str,實際上就是傳遞了裝載指針的容器歹鱼,這樣以來我們就可以把在子函數(shù)中動態(tài)分配的內(nèi)存空間的首地址放到了這個“容器”中了(即是str被賦值上了新分配內(nèi)存的首地址)泣栈。在一次編譯執(zhí)行,無段錯誤弥姻,結(jié)果輸出“hello”字符串南片。也就完美地解決了這道錯誤非常隱蔽的面試題。同樣有的同學(xué)會想庭敦,把NULL掉咋樣?編譯運行發(fā)現(xiàn)還是出現(xiàn)段錯誤疼进,還是同樣的問題:指針str屬于局部變量,系統(tǒng)會隨機分配一個地址給str,同樣是指針常量賦值秧廉。 而當我們解決了這道題伞广,我們能夠感受到指針的靈活性和操作的隱蔽性,我們也就知道了常量是不能被賦值的(因為他被系統(tǒng)認為是只讀)疼电,還知道了將一個二級指針作為參數(shù)傳遞可以保存一個地址的值嚼锄,這也是編程的一個技巧。

接下來我們在看一看第二道題:

問題二:

以下代碼段的執(zhí)行結(jié)果?

int main(int argc, const char *argv[])

{

int i,n=0;

for(i=1;i

{

n=10*n+*argv[i]-'0';

}

printf("%d\n",n);

return 0;

}

./a.out 12 345 678

雖然代碼很簡練蔽豺,但是如果不細心分析還是很難把這道題答案寫出來的区丑,甚至是沒有任何思路。實際上這道題考察的是大家對于指針的掌握和ascii的一些知識:大家一定要理解*argv[i]意思修陡,如果不注意可能會認為是取命令行參數(shù)的第二個字符串的值沧侥,其實不然,這樣理解的話大家對于指向一個字符串的字符指針的的不理解濒析,指向一個字符串的字符指針實際上是指向一個字符串首字符的地址正什,命令行參數(shù)輸入的12 345 678看似數(shù)字,實際上是一個個字符串号杏,*argv[i]的意思也就是取各自字符串的首字符也就是取1婴氮、3、6盾致,說到這里這道面試題也就引刃而解了主经。那么*argv[i]-'0'是啥意思呢?很顯然嗎,就是將ascii表示的字符轉(zhuǎn)化為對應(yīng)的數(shù)字也就是數(shù)字1庭惜、3罩驻、6。到這里我們在通過推理就得到了最終的結(jié)果:136护赊。

通過了這一番地分析是不是也挺簡單的惠遏,那必須的啊砾跃,通過這道面試題我們也就知道了:指向一個字符串的指針實際上就是把字符串的首地址賦給了指針變量,還有就是一個字符減去’0’就能得到字符所對應(yīng)的數(shù)字节吮。

當然這只是兩道比較易錯的使用指針的面試題抽高,很多面試題都是從大家對指針本質(zhì)的認識上著手來考察大家,只要掌握指針的本質(zhì)透绩,了解常見段錯誤的產(chǎn)生的原因和處理方案翘骂,了解C語言內(nèi)存的分配情況就能煉就一雙”火眼金睛“,從本質(zhì)上真正精通C語言帚豪。以上也是本人通過實踐和深入的分析得出的一些經(jīng)驗碳竟,如若有更加簡單易懂的方案望給出寶貴意見,待以后修正完善狸臣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莹桅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子固棚,更是在濱河造成了極大的恐慌统翩,老刑警劉巖仙蚜,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件此洲,死亡現(xiàn)場離奇詭異,居然都是意外死亡委粉,警方通過查閱死者的電腦和手機呜师,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贾节,“玉大人汁汗,你說我怎么就攤上這事±跬浚” “怎么了知牌?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斤程。 經(jīng)常有香客問我角寸,道長,這世上最難降的妖魔是什么忿墅? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任扁藕,我火速辦了婚禮,結(jié)果婚禮上疚脐,老公的妹妹穿的比我還像新娘亿柑。我一直安慰自己,他們只是感情好棍弄,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布望薄。 她就那樣靜靜地躺著疟游,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痕支。 梳的紋絲不亂的頭發(fā)上乡摹,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音采转,去河邊找鬼聪廉。 笑死,一個胖子當著我的面吹牛故慈,可吹牛的內(nèi)容都是我干的板熊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼察绷,長吁一口氣:“原來是場噩夢啊……” “哼干签!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拆撼,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤容劳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后闸度,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竭贩,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年莺禁,在試婚紗的時候發(fā)現(xiàn)自己被綠了留量。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡哟冬,死狀恐怖楼熄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浩峡,我是刑警寧澤可岂,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站翰灾,受9級特大地震影響缕粹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜预侯,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一致开、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萎馅,春花似錦双戳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魄衅。三九已至,卻和暖如春塘辅,著一層夾襖步出監(jiān)牢的瞬間晃虫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工扣墩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哲银,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓呻惕,卻偏偏與公主長得像荆责,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子亚脆,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 計算機二級C語言上機題庫(南開版) 1.m個人的成績存放在score數(shù)組中做院,請編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,322評論 1 42
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運用指針編程是C語言最主要的風格之一濒持。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu)键耕; ...
    朱森閱讀 3,424評論 3 44
  • 一、(一共三十題) 1.main() { int a[5]={1,2,3,4,5}; int *ptr=(int ...
    iOS_Alex閱讀 943評論 0 0
  • 一柑营、(一共三十題) 1.main() { int a[5]={1,2,3,4,5}; int *ptr=(int ...
    iOS_Alex閱讀 731評論 0 2
  • 題目類型 a.C++與C差異(1-18) 1.C和C++中struct有什么區(qū)別屈雄? C沒有Protection行為...
    阿面a閱讀 7,633評論 0 10