下午寫代碼時,碰到了一隻bug,弄了好一會兒才發現。先貼一下含有bug 的原始碼,標紅處是bug:
void CreateGraph(MGraph *G)
{
printf("請輸入圖的類型,1表示有向圖,0表示無向圖。");
scanf("%d",&G->graphkind);
if(G->graphkind==1)
{
printf("現在構建有向圖。");
CreateDG(&G);
}//構造有向圖。此處不應該使用取地址符
else if(G->graphkind==0)
{
printf("現在構建無向圖。");
CreateUDG(&G);
}//構造無向圖。此處不應該使用取地址符
else
{printf("Wrong!");
exit(0);}
}
}
void CreateUDG(MGraph *G)//構造無向圖。
{
此處省略代碼若干行......
}
void main()
{
MGraph graph1;
CreateGraph(&graph1);
}
bug分析:
從上面的代碼可以看到,我寫了兩個使用指標型形參的函數,第二個函數CreateUDG被第一個函數CreateGraph嵌套調用。
一般我們調用指標形參的函數時,都是這樣寫的:
void funA(int *a)
{
........
}
int argue1;
funA(&argue1);
我們把argue1的地址傳遞到funA裡頭,這樣在funA裡對a地址所指向資料進行修改後,argue1的值也進行相應的改變(如果不是指標形參,則argue1的值在函數外並未發生改變,改變的只是函數的局部變數a)。調用時我們使用取地址符&argue1,表示對argue1取了地址。
但是平常這樣寫順手後,當函數間有嵌套關係,且互相嵌套的函數都使用指標型時bug就產生了。上面錯誤的程式碼片段中,在主函數中我們調用CreateGraph(&graph1),已經將graph1的地址傳遞給CreateGraph函數了,所以在該函數中G代表的就是graph1的地址,所以在CreateGraph中嵌套調用CreateDG時,其實參不需要再取地址符,因為傳過去的G本身就已經是地址了嘛,地址的地址是沒有意義的。
所以以後寫指標型形參的函數時,特別是進行了嵌套調用,一定要分析形參實參傳遞進來的到底是什麼,不要寫得順手,寫得抽筋啦。
值得一提的是,這個bug,VC6.0的編譯器不會報錯,但是會給個warning。這樣的話,程式可以執行,但是返回的卻不是你想要的。。。推而廣之,如果以後再有程式猿告訴你寫程式嘛管管error就好warning就忽略掉吧,那你就可得三思了,不然也許你只好像我一樣瞪大眼睛找bug了。