/----------------------------------------------------------------------/
二。main的聲明
其實(shí)如果只是算潭書(shū)的第二版,這個(gè)無(wú)類型的main聲明沒(méi)有問(wèn)題,只是直到C99標(biāo)準(zhǔn)
的出現(xiàn),這個(gè)聲明才徹底廢除。其實(shí)也是同樣一個(gè)問(wèn)題,允許你不寫(xiě),但這不是說(shuō)你
這樣用就是好事。不過(guò),這個(gè)的后果有點(diǎn)不一樣的就是,你忽略不寫(xiě),很可能以為是
不需要返回的,或者是以為返回一個(gè)無(wú)類型的(void),接著就出現(xiàn)了main函數(shù)里不
寫(xiě)return 0;的問(wèn)題。那本書(shū)就是從頭到尾所有main函數(shù)一律沒(méi)有return 0; 。好了,
等到學(xué)了函數(shù)那章,書(shū)上說(shuō),沒(méi)有返回值的函數(shù)應(yīng)該要用void來(lái)聲明,好了,
void main就這樣誕生了。不信就看看譚書(shū)的第三版,變成從頭到尾的void main()。
不過(guò)話說(shuō)回頭,這樣的問(wèn)題對(duì)于初學(xué)者學(xué)習(xí)基本語(yǔ)法和結(jié)構(gòu)方面和寫(xiě)寫(xiě)小程序的都不會(huì)
出現(xiàn)任何影響。在編譯器上來(lái)說(shuō),這只是一個(gè)標(biāo)準(zhǔn)的問(wèn)題,但對(duì)于你來(lái)說(shuō)別小看了這么
一點(diǎn)點(diǎn)的變化。因?yàn)槟懔?xí)慣了main這種寫(xiě)法的話,必然會(huì)把這個(gè)習(xí)慣帶到編寫(xiě)其它函數(shù)里
(這里暫且不講main本身返回值的問(wèn)題)。
舉個(gè)簡(jiǎn)單例子,寫(xiě)以下代碼:
#include <stdio.h>
factorial(int n)
{
if(n==1)return 1;
else if(n>1)return n * factorial(n-1);
}
int main(void)
{
int n;
while(scanf("%d", &n),n>=0)
{
printf("%d\n", factorial(n));
}
return 0;
}
看得出來(lái)是計(jì)算階乘的(主要看那個(gè)子函數(shù),main函數(shù)用回標(biāo)準(zhǔn)寫(xiě)法),
只不過(guò)少了int聲明和最后一個(gè)必然的return而已,
看看輸入一個(gè)0進(jìn)去會(huì)發(fā)生什么事吧:
TC2: 1 (結(jié)果居然是碰對(duì)了)
VC6: -858993460 (不確定的隨機(jī)結(jié)果)
GCC: 0 (C99標(biāo)準(zhǔn))
如果你用TC,那你還可能以為這份代碼是正確的,
于是你就以為遞歸算階乘就是這么寫(xiě)的。
于是還反過(guò)來(lái)問(wèn)我:“喂,雨中飛燕,這個(gè)結(jié)果不就是正確的嗎,還錯(cuò)什么?”
于是我無(wú)語(yǔ)了。。。然后你也就留下了一個(gè)你可能以后都不打算去檢查的Bug。。。
現(xiàn)在我們?cè)賮?lái)看一個(gè):
#include <stdio.h>
long Factorial(int n)
{
if(n==1)return 1;
else if(n>1)return n * Factorial(n-1);
return 1;
}
FactorialSum(int n)
{
float f = 0;
for(;n>0;--n)
{
f += 1.0/Factorial(n);
}
return f;
}
int main(void)
{
int n;
while(scanf("%d", &n),n>=0)
{
printf("%f\n", FactorialSum(n));
}
return 0;
}
這個(gè)是計(jì)算1/1! + 1/2! + 1/3! +...+ 1/n!的代碼,F(xiàn)actorial的改好了,
然后加一個(gè)FactorialSum函數(shù)計(jì)算和。里面的變量f就是用來(lái)累加(喜歡用float來(lái)
保存浮點(diǎn)也是書(shū)上的一大不良特色),1寫(xiě)成1.0保證結(jié)果不是整數(shù)。似乎沒(méi)錯(cuò)吧?
運(yùn)行一下不就知道了嘛,輸入1,輸出0;輸入2,輸出0;輸入5,輸出0,
結(jié)果是輸出全部是0。原因就是你省略類型埋的禍根,只需要在那個(gè)函數(shù)前面補(bǔ)上
一個(gè)float那結(jié)果就正確了。
這個(gè)危害有多嚴(yán)重嗎?在這里不算嚴(yán)重,因?yàn)樵谶@里代碼很短,相當(dāng)容易看得出來(lái)。
要是換成大程序呢?上千代碼甚至上萬(wàn)的代碼,要是最后都懶得寫(xiě)一下return,
或者一個(gè)返回類型,那么錯(cuò)誤還怎么找?你要是這個(gè)也省略那個(gè)也省略,
寫(xiě)了N多行代碼的時(shí)候,一運(yùn)行,這個(gè)結(jié)果也錯(cuò)那個(gè)輸入也不行的時(shí)候,
你再看看你是不是被你自己的“習(xí)慣”給難住你自己吧。
其實(shí)說(shuō)實(shí)在的,WIN-TC自帶的一個(gè)tcsearch.exe文件,那個(gè)可以查函數(shù)用法和示例,
上面的示例代碼全部都是一樣的風(fēng)格: int main(void)
非常規(guī)范標(biāo)準(zhǔn)的寫(xiě)法,可是有多少人看了這個(gè)了呢?