void main()是错误的
?????? USE_NET新聞組一直苦惱于一個問題的討論,我們能否用void作為一個main的返回類型,ANSI標準說不能,然而,大量的關于C的啟蒙書中的例子都使用了void main (void),這讓許多人感覺不知該如何是好。
??????? 當有人問為什么使用void是錯誤的時候,(即使它能正常工作),回答往往是下面中的一個:
因為標準這么說(這種回答通常是針對這這種問題"它能正常工作!")
因為調用main()的啟動程序可以被認為是入棧,如果main()不這么做,在程序退出時將導至stack corruption的問題,并且 引發沖突。(這種回答通常是針對這這種問題"它能正常工作!")
因為你可能給調用環境返回一個隨機值,這是很糟糕的,因為如果有人想要檢測你的程序是否失敗了,或者從一個makefile中調用你的程序,那么它們將不能保證非零的返回值就是失敗。(這樣的回答通常是針對這種問題"那是他們的問題")。
?????? 這里我們舉一個系統的例子去證明void main(void)程序在上面第三條里將要引起的問題。從一個腳本調用程序可能引起腳本的崩潰。不管它的返回碼是否被檢測到。從一個makefile調用它可能引起make的問題。從命令行調用它可能引起一個錯誤報告。
?????? RISC OS 是一種本地的操作系統,這個系統的方便之處是有一個系統變量Sys$RCLimit.這個變量的值是用來指定一個程序可以返回到系統的最大值,這個變量的默認值被系統設置為256.我不能確認這個變量的目的,但是它是確定存在的。
?????? 現在,讓我們看一個用int main(void)的例子程序
?????? int main(void)
?????? {
?????????????? return 42;
?????? }
?
?????? 把它翻譯成匯編語言,用gcc(Acorn自己的C編譯會報告一個警告,并把它轉換成一個返回值為0的整型函數):
|main|:
??????? mov???? ip, sp?
??????? stmfd?? sp!, {rfp, fp, ip, lr, pc}
??????? sub???? fp, ip, #4
??????? cmps??? sp,sl
??????? bllt??? |x$stack_overflow|
??????? bl????? |___main|
??????? mov???? r0, #42
??????? ldmdb?? fp, {rfp, fp, sp, pc}^
?
??????? 第六個指令是初始化和堆棧檢測,最后兩個返回42到庫的啟動碼,所以main的返回值被傳遞到R0.標記庫啟動碼將要去調用一個整型的返回函數,所以能夠使用R0的返回值。
??????? void main function發生了什么?好的,這兒是一個例子。
?????? #include <stdio.h>
?????? char buf[1024];
?????? void main(void)
?????? {
???????????? (void)fgets(buf, 1024, stdin);
??????? }?
??????? 程序在他的標準輸入端口等待一行文本的輸入,我們把它編譯成匯編語言:?? |.LC0|:
??????? dcd???? |__iob|
|.LC1|:
??????? dcd???? |buf|
|main|:
??????? mov???? ip, sp?
??????? stmfd?? sp!, {rfp, fp, ip, lr, pc}
??????? sub???? fp, ip, #4
??????? cmps??? sp,sl
??????? bllt??? |x$stack_overflow|
??????? bl????? |___main|
??????? ldr???? r2, [pc, #|.LC0| - . - 8]
??????? mov???? r1, #1024
??????? ldr???? r0, [pc, #|.LC1| - . - 8]
??????? bl????? |fgets|
??????? ldmdb?? fp, {rfp, fp, sp, pc}^
??????? area??? |buf|, DATA, COMMON, NOINIT
??????? %?????? 1024??????? 第六個指令是啟動,下面的三個為fgets的調用設置參數,那么我們調用fgets并且返回到調用者。stdio.h中說fgets返回一個指針到緩存,所以,在這個實例中,我們返回到庫啟動碼的是一個指向buf的指針,在RISC OS中,所有C程序被映射到內存地址0x8000.所以,我們將返回一個 > 32768 的值到操作系統中,(因此,大于Sys$RCLimit默認的值).系統產生錯誤。
?????? 這兒是編譯和運行程序的結果:
??????? SCSI: void % gcc void.c -o void
??????? Drlink AOF Linker? Version 0.28? 30/07/95
??????? SCSI: void % show Sys$RCLimit
??????? Sys$RCLimit : 256
??????? SCSI: void % void
??????? I enter this line
??????? Return code too large
??????? SCSI: void %
??????? And, in a script file:
??????? SCSI: void % cat script
??????? void
??????? echo Finished
??????? SCSI: void % run script
??????? I enter this line
??????? Return code too large
??????? SCSI: void %???
??????? 在第二個命令運行之前,錯誤中斷了程序????????
??????? 注意,上面的例子是一個小的人為的目的去使最終函數調用返回一個指針。一個更好的例子是程序用printf:????????
string > 256時也會返回錯誤,依賴用戶輸入字符的長度,程序是否可能返回一個錯誤在于用void作為main類型的返回
所以,如果你想要你的軟件更有笑,請讓main返回int,這樣會做的更好。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/jia_xiaoxin/archive/2008/08/25/2826868.aspx
轉載于:https://www.cnblogs.com/javaTest/archive/2010/05/14/2589543.html
總結
以上是生活随笔為你收集整理的void main()是错误的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ie6 下最佳 PNG透明方案【转】
- 下一篇: poj 3256(DFS)