日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁(yè)編程開(kāi)發(fā)VC|VC++ → TC過(guò)時(shí)了嗎,Turbo C 的一些問(wèn)題

      TC過(guò)時(shí)了嗎,Turbo C 的一些問(wèn)題

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:本站整理時(shí)間:2010/10/3 23:01:49字體大。A-A+

      作者:佚名點(diǎn)擊:559次評(píng)論:1次標(biāo)簽: TC turboc

      • 類型:修改器大小:539KB語(yǔ)言:中文 評(píng)分:7.0
      • 標(biāo)簽:
      立即下載

      “TC過(guò)時(shí)了”,我說(shuō)。接著就一堆人問(wèn),“為什么過(guò)時(shí)。俊,“TC不是很好用嗎”,
      “教材上也是用這個(gè)啊”,“二級(jí)考試不也是規(guī)定用的TC嗎?”。
      于是乎我已經(jīng)無(wú)語(yǔ)了。


      /----------------------------------------------------------------------/
      一。頭文件的問(wèn)題

      好了,來(lái)看個(gè)經(jīng)典的TC2下在老潭的書(shū)的《C語(yǔ)言程序設(shè)計(jì)(第二版)》,
      第4頁(yè)的一段代碼:
      main( )
      {
      printf("This is a C program.\n");
      }
      好了,當(dāng)時(shí)的TC2的確允許使用printf和scanf可以不加頭文件,
      也的確允許main()這樣的聲明。允許是允許了,可是你寫成這樣對(duì)你有好處嗎?

      打個(gè)比方,Basic語(yǔ)言知道嗎?這種語(yǔ)言可以不聲明變量就使用。
      的確同樣也是允許了,可是給我的話,我會(huì)要求編譯器強(qiáng)制檢查變量是不是聲明了再使用。
      為什么?如果你需要用名字是nlen這個(gè)變量,當(dāng)中有一個(gè)不小心寫成n1en,
      不強(qiáng)制檢查的話,編譯器不告訴你錯(cuò),但運(yùn)行結(jié)果是錯(cuò)誤的。但這種錯(cuò)誤要是在很多行
      代碼里你怎么找?特別是'l'和'1'如此相似。

      編譯器雖然允許,但你別以為那樣寫就是好事。說(shuō)回剛剛的C代碼,TC2允許不加頭文件,
      于是不少初學(xué)的人習(xí)慣了從不寫頭文件,以為C語(yǔ)言不需要頭文件似的。
      好了,等到看到那本書(shū)的138頁(yè),那個(gè)字符輸入輸出,用了gets,
      就突然多了一個(gè)#include <stdio.h>,仔細(xì)一看,那一頁(yè)中間有100來(lái)字強(qiáng)調(diào)
      了要用庫(kù)函數(shù),可是沒(méi)有講怎么用,下面多了的那一行初學(xué)者也可能會(huì)覺(jué)得奇怪,
      要是不理解的人就跳過(guò)了,要是沒(méi)留意的更不當(dāng)一回事了,誰(shuí)讓之前書(shū)里一直都
      沒(méi)有那句呢。然后,當(dāng)有的初學(xué)者用TC3.0打代碼的時(shí)候,編譯提示說(shuō)scanf沒(méi)有
      聲明(或者是用TC2的打了gets函數(shù)說(shuō)gets沒(méi)有聲明),他們就郁悶了,
      都是按照書(shū)的代碼啊,都一模一樣還會(huì)錯(cuò)?于是跑來(lái)論壇問(wèn)。有跑來(lái)問(wèn)的還好,
      最怕的就是用TC2的,看了數(shù)組覺(jué)得難還跳了過(guò)去的,于是一直都不會(huì)寫頭文件,
      成了習(xí)慣。要是隨便換個(gè)環(huán)境,結(jié)果沒(méi)寫頭文件的,錯(cuò)了,結(jié)果還說(shuō)自己寫C代碼
      寫那么多,這里怎么就錯(cuò)了,然后就懷疑編譯器是不是壞的。然后就借口說(shuō)這個(gè)
      用不習(xí)慣要換TC2。結(jié)果就是惡性循環(huán),跳不出TC2,學(xué)不到新領(lǐng)域的東西。
      論壇上這種代碼絕不少見(jiàn),隨便翻一些提問(wèn)帖子肯定找得到。其實(shí)早在TC3.0已經(jīng)
      不再允許scanf和printf不加頭文件了,隨后的所有C編譯器也不再支持TC2的
      這個(gè)特性了。


      /----------------------------------------------------------------------/
      二。main的聲明

      其實(shí)如果只是算潭書(shū)的第二版,這個(gè)無(wú)類型的main聲明沒(méi)有問(wèn)題,只是直到C99標(biāo)準(zhǔn)
      的出現(xiàn),這個(gè)聲明才徹底廢除。其實(shí)也是同樣一個(gè)問(wèn)題,允許你不寫,但這不是說(shuō)你
      這樣用就是好事。不過(guò),這個(gè)的后果有點(diǎn)不一樣的就是,你忽略不寫,很可能以為是
      不需要返回的,或者是以為返回一個(gè)無(wú)類型的(void),接著就出現(xiàn)了main函數(shù)里不
      寫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)方面和寫寫小程序的都不會(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這種寫法的話,必然會(huì)把這個(gè)習(xí)慣帶到編寫其它函數(shù)里
      (這里暫且不講main本身返回值的問(wèn)題)。
      舉個(gè)簡(jiǎn)單例子,寫以下代碼:
      #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)寫法),
      只不過(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,那你還可能以為這份代碼是正確的,
      于是你就以為遞歸算階乘就是這么寫的。
      于是還反過(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寫成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)的代碼,要是最后都懶得寫一下return,
      或者一個(gè)返回類型,那么錯(cuò)誤還怎么找?你要是這個(gè)也省略那個(gè)也省略,
      寫了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)的寫法,可是有多少人看了這個(gè)了呢?

      /----------------------------------------------------------------------/
      三。函數(shù)聲明與返回值

      經(jīng)典的老代碼:
      int max(x,y)
      int x,y;
      {
      return x>y ? x : y;
      }
      現(xiàn)在早已不是pascal時(shí)代了,這樣的函數(shù)聲明不但難讀,并且現(xiàn)在C99標(biāo)準(zhǔn)已經(jīng)不再
      支持這種寫法了。在老潭的書(shū)也僅僅用了半版不到的篇幅提到了一下,
      其它地方并沒(méi)有使用這種聲明,這點(diǎn)做得還不錯(cuò)。不過(guò)很奇怪的是論壇上還時(shí)不時(shí)
      能看見(jiàn)這種聲明,這個(gè)到底是拜誰(shuí)所賜呢?這我就不知道了,這里也不展開(kāi)來(lái)講了。


      /----------------------------------------------------------------------/
      四。代碼風(fēng)格

      這個(gè)問(wèn)題就非常嚴(yán)重了,F(xiàn)在的情況是,從代碼風(fēng)格,就可以知道你的大概水平了,
      至少能知道你是不是菜鳥(niǎo)。那些代碼縮進(jìn)弄得亂七八糟的,不用看詳細(xì)代碼都知道
      水平肯定高不到哪里去(當(dāng)然不排除你可以故意弄亂)。因?yàn)橐亲鳛橐粋(gè)新手,
      要是寫的代碼亂,調(diào)試的時(shí)候或者自己看自己的代碼的時(shí)候,要是你自己都覺(jué)得亂,
      當(dāng)代碼有Bug,你要找出來(lái)的話,看你還頭痛不頭痛了。本來(lái)代碼就有問(wèn)題,再加上
      格式亂,要是你自己看著都不舒服,那你還怎么去調(diào)試代碼呢?自己不會(huì)看著頭暈?
      代碼少的時(shí)候你可能不覺(jué)得,等你寫了上百行代碼的那再嘗嘗這種滋味吧。

      更嚴(yán)重的問(wèn)題是,DOS原版TC對(duì)縮進(jìn)支持不好,
      格式的控制相對(duì)其它的編輯器來(lái)說(shuō)都要弱。
      對(duì)于初學(xué)者,很容易弄出參差不齊的代碼,
      對(duì)于學(xué)習(xí)方面來(lái)說(shuō)這是一個(gè)很不利的因素。

      再者,大括號(hào)的位置及變量聲明位置的問(wèn)題。看以下幾種風(fēng)格:
      1.
      int main(void) //潭氏風(fēng)格
      {int n,s;
      while(scanf("%d", &n),n>=0)
      {
      s = factorial(n);
      printf("%d\n", s);
      }
      return 0;
      }
      2.
      int main(void) //視頻教學(xué)風(fēng)格?
      { int n,s;
      while(scanf("%d", &n),n>=0)
      { s = factorial(n);
      printf("%d\n", s);
      }
      return 0;
      }
      3.
      int main(void) //不知道這風(fēng)格的來(lái)源
      {
      int n,s;
      while(scanf("%d", &n),n>=0)
      {
      s = factorial(n);
      printf("%d\n", s);
      }
      return 0;
      }
      4.
      int main(void){ //這種風(fēng)格也有不少高手使用的
      int n,s;
      while(scanf("%d", &n),n>=0){
      s = factorial(n);
      printf("%d\n", s);
      }
      return 0;
      }
      5.
      int main(void) //C Primer Plus 上的風(fēng)格
      {
      int n;
      while(scanf("%d", &n),n>=0)
      {
      int s = factorial(n);
      printf("%d\n", s);
      }
      return 0;
      }
      我推薦的寫法是第5種。第三種寫法貌似較少見(jiàn),雨中飛燕本人不好作出評(píng)論。
      但對(duì)于1,2,4三種寫法,都是有原因的。原因也很簡(jiǎn)單,減少占用的行數(shù)。
      特別是紙版書(shū),節(jié)省這點(diǎn)行數(shù)累積起來(lái)可以節(jié)約不少紙張,降低書(shū)的成本。
      對(duì)于powerpoint演示,如果不節(jié)約行數(shù),代碼根本沒(méi)辦法顯示完。
      但你要注意,它這樣寫可能不是為了告訴你要這樣寫出這樣緊密的代碼。
      但同樣的問(wèn)題出現(xiàn)在TC上。DOS窗口標(biāo)準(zhǔn)大小80*25,高度只能顯示25行,
      再加上TC菜單和最下面的輸出窗口,你能同時(shí)看到最多20行,要是按第5種風(fēng)格
      來(lái)寫代碼,會(huì)看得很辛苦(因?yàn)門C2用不了鼠標(biāo),TC3能用不過(guò)也麻煩),
      于是造成N多緊縮型代碼。如果你換成現(xiàn)在新的編輯軟件,根本用不著這樣。
      Windows上的集成編輯軟件一頁(yè)下來(lái)就是三四十行,用鼠標(biāo)滾輪滾一下就能上下拉,
      一個(gè)代碼塊要是不想看還可以折疊起來(lái),這些特性都是TC所無(wú)法比擬的,
      都比TC方便得多。你還有什么理由抱著TC不放呢?還何必寫緊縮型代碼來(lái)為難
      自己的那雙眼睛呢?


      /----------------------------------------------------------------------/
      五。TC圖形庫(kù)

      TC圖形庫(kù)這個(gè)可以說(shuō)是TC一大特色,用TC2寫出來(lái)的代碼一般可以一眼看出,因?yàn)門C2
      編譯運(yùn)行的時(shí)候,屏幕上原有的東西并不會(huì)清除,所以用TC的人一般會(huì)習(xí)慣在程序開(kāi)頭
      寫上clrscr()。當(dāng)然,要是用Win-TC就不會(huì)發(fā)生這種情況。如果使用者本人知道這個(gè)
      庫(kù)是TC專有(好比是VC的MFC)的話,這倒問(wèn)題不大。問(wèn)題是如果使用者不知道的話,
      屏幕輸出用習(xí)慣了gotoxy,變得理所當(dāng)然地認(rèn)為C就應(yīng)該支持這類函數(shù)的話,
      那就糟糕了。論壇上跑來(lái)問(wèn)VC6可不可以輸出圖形,或者問(wèn)有沒(méi)有g(shù)otoxy函數(shù)的人
      不是一個(gè)兩個(gè)人的問(wèn)題了。


      /----------------------------------------------------------------------/
      六。越界檢查
      由于在DOS下,DOS系統(tǒng)根本不會(huì)去檢查程序的訪問(wèn)越界問(wèn)題,無(wú)論你要對(duì)內(nèi)存的哪里
      進(jìn)行讀寫,都是允許的(只要不把自己程序的代碼區(qū)改寫了就沒(méi)事)。但在Windows下,
      尤其是WinXP,內(nèi)存是分塊的,對(duì)只讀塊寫數(shù)據(jù)或者對(duì)不可讀寫塊進(jìn)行讀數(shù)據(jù)都會(huì)引發(fā)
      異常,如果程序不能夠處理這個(gè)異常,那么這個(gè)程序就會(huì)被強(qiáng)制關(guān)閉。有了這個(gè)異常
      機(jī)制,當(dāng)然會(huì)使你更容易查出程序的錯(cuò)誤。特別地,在VC6的Debug模式下,
      堆里未被初始化的內(nèi)存被0xCD字節(jié)模式填充,堆里釋放的內(nèi)存被0xDD字節(jié)模式填充。
      于是一但發(fā)生越界的時(shí)候,很容易通過(guò)程序運(yùn)行結(jié)果得知當(dāng)中有錯(cuò),為調(diào)試帶來(lái)了方便。
      然而TC則不然,不管你越界了多少,你都收不到任何的警告或者錯(cuò)誤。
      而且在多數(shù)情況下,TC下運(yùn)行正常的越界代碼換VC6上就會(huì)結(jié)果出錯(cuò)。
      有初學(xué)者以為這是VC6編譯器有問(wèn)題,其實(shí)不然,而是TC給你掩蓋了這個(gè)錯(cuò)誤。
      #include <stdio.h>
      int main(void)
      {
      int n;
      int num[8];
      int sum[8] = {0};
      for(n=1;n<=8;++n)num[n] = 1;
      for(n=1;n<8;++n)sum[n] = num[n]+num[n+1];
      for(n=1;n<8;++n)
      printf("%d\n", sum[n]);
      getchar();
      return 0;
      }
      這個(gè)程序的目的是給num數(shù)組全部給1,然后sum數(shù)組計(jì)算num相鄰兩個(gè)數(shù)的和。
      有的初學(xué)者可能會(huì)說(shuō),這個(gè)程序沒(méi)問(wèn)題,如果他以為int num[8];的下標(biāo)是從1至8的話。
      然后,照樣運(yùn)行一下看看。TC的結(jié)果是7個(gè)2,結(jié)果正常。
      VC6的結(jié)果是,什么都沒(méi)有顯示,然后你打開(kāi)資源管理器查看一下進(jìn)程,
      你就會(huì)發(fā)現(xiàn)這個(gè)程序占用CPU高達(dá)90%以上。你不要以為這是編譯器發(fā)生了問(wèn)題,
      原因正是因?yàn)檫@里的越界導(dǎo)致了一個(gè)死循環(huán)!如果是GCC或更高版本的VC編譯器,
      把for里的8改成11也會(huì)發(fā)生死循環(huán)。但即使改成11,在TC上運(yùn)行的結(jié)果也非常正常,
      TC里完全沒(méi)有任何錯(cuò)誤的征兆。這里不分析這個(gè)死循環(huán)產(chǎn)生的原因,這里只是想告訴你,
      你在TC上運(yùn)行結(jié)果無(wú)誤的程序不一定就邏輯上正確了(包括VC和GCC)。特別是TC幾乎
      沒(méi)有任何的越界檢查,所以更要求程序員在TC上編寫代碼時(shí)候要十分謹(jǐn)慎和細(xì)心。
      但現(xiàn)在問(wèn)題是現(xiàn)在使用TC的大多是初學(xué)者,在沒(méi)有什么經(jīng)驗(yàn)的情況下,很大可能
      會(huì)寫出類似這樣的越界訪問(wèn)代碼。這種代碼也許在TC上沒(méi)有問(wèn)題,可是只要換一個(gè)
      編譯環(huán)境,問(wèn)題就馬上暴露出來(lái)了。不信就看看下面的經(jīng)典TC錯(cuò)誤代碼吧:
      #include <stdio.h>
      int main(void)
      {
      char *pstr;
      gets(pstr);
      puts(pstr);
      getchar();
      return 0;
      }
      (別告訴我說(shuō)你不知道這代碼錯(cuò)在哪里,你不知道錯(cuò)哪里的話那你平時(shí)一定是使用TC的)


      /----------------------------------------------------------------------/
      七。結(jié)束語(yǔ)

      現(xiàn)在再來(lái)回答文章一開(kāi)頭的內(nèi)容:“為什么說(shuō)TC過(guò)時(shí)”?
      主要原因其實(shí)不是過(guò)時(shí)不過(guò)時(shí)的問(wèn)題,主要是不適合現(xiàn)在初學(xué)C語(yǔ)言的學(xué)生們使用。
      很容易因?yàn)門C過(guò)于寬松的一些語(yǔ)法,或者一些與C99標(biāo)準(zhǔn)不一樣的語(yǔ)法,
      讓初學(xué)者養(yǎng)成不良習(xí)慣或者產(chǎn)生特定環(huán)境下的依賴性。這些都是對(duì)學(xué)習(xí)上不利的因素。
      所以我一般給別人推薦DevC++或者VC2005就是這個(gè)原因,借助編譯器的強(qiáng)制能力,
      迫使你使用較為規(guī)范的方式去寫代碼。新加坡的環(huán)境為什么好?不是因?yàn)楣袼刭|(zhì)高,
      是因?yàn)橛蟹梢?guī)定,隨便扔垃圾或者破壞環(huán)境的都會(huì)有嚴(yán)重的法律后果。

      歸根究底,不讓你用TC,就是不希望你有不良習(xí)慣,更何況有很多比TC優(yōu)秀的編譯器呢?
      何必因?yàn)榻滩幕蛘呖荚囀荰C,你就一定用TC呢?

      知識(shí)是屬于自己的,用來(lái)真正充實(shí)你自己的
      考試是給別人看的,用來(lái)得到一時(shí)之虛榮的
      你希望得到充實(shí),還是一時(shí)之虛榮?

       

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過(guò)難過(guò)
        • 5 囧
        • 3 圍觀圍觀
        • 2 無(wú)聊無(wú)聊

        熱門評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(1)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)