`
VincentZheng
  • 浏览: 52158 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

【转】C/C++ 误区一:void main()

    博客分类:
  • C
 
阅读更多
很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着 The definition void main( ) { /* ... */ } is not and never has been C++, nor has it even been C.( void main( ) 从来就不存在于 C++ 或者 C )。下面我分别说一下 C 和 C++ 标准中对 main 函数的定义。

1. C

在 C89 中,main( ) 是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的经典巨著 The C programming Language 2e(《C 程序设计语言第二版》)用的就是 main( )。不过在最新的 C99 标准中,只有以下两种定义方式是正确的:
int main( void )
int main( int argc, char *argv[] )
参考资料:ISO/IEC 9899:1999 (E) Programming languages — C 5.1.2.2.1 Program startup)

当然,我们也可以做一点小小的改动。例如:char *argv[] 可以写成 char **argv;argv 和 argc 可以改成别的变量名(如 intval 和 charval),不过一定要符合变量的命名规则。

如果不需要从命令行中获取参数,请用int main(void) ;否则请用int main( int argc, char *argv[] ) 。

main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的调用者(如操作系统)。

如果 main 函数的最后没有写 return 语句的话,C99 规定编译器要自动在生成的目标文件中(如 exe 文件)加入return 0; ,表示程序正常退出。不过,我还是建议你最好在main函数的最后加上return 语句,虽然没有这个必要,但这是一个好的习惯。注意,vc6不会在目标文件中加入return 0; ,大概是因为 vc6 是 98 年的产品,所以才不支持这个特性。现在明白我为什么建议你最好加上 return 语句了吧!不过,gcc3.2(Linux 下的 C 编译器)会在生成的目标文件中加入 return 0; 。

2. C++

C++98 中定义了如下两种 main 函数的定义方式:
①int main( )
②int main( int argc, char *argv[] )
参考资料:ISO/IEC 14882(1998-9-01)Programming languages — C++ 3.6 Start and termination)

int main( ) 等同于 C99 中的 int main( void ) ;int main( int argc, char *argv[] ) 的用法也和 C99 中定义的一样。同样,main 函数的返回值类型也必须是int。如果main函数的末尾没写return语句,C++98 规定编译器要自动在生成的目标文件中加入 return 0; 。同样,vc6 也不支持这个特性,但是 g++3.2(Linux 下的 C++ 编译器)支持。

3. 关于 void main( )

在 C 和 C++ 中,不接收任何参数也不返回任何信息的函数原型为“void foo(void);”。可能正是因为这个,所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的!main 函数的返回值应该定义为 int 类型,C 和 C++ 标准中都是这样规定的。虽然在一些编译器中,void main 可以通过编译(如 vc6),但并非所有编译器都支持 void main ,因为标准中从来没有定义过 void main 。g++3.2 中如果 main 函数的返回值不是 int 类型,就根本通不过编译。而 gcc3.2 则会发出警告。所以,如果你想你的程序拥有很好的可移植性,请一定要用 int main 。

4. 返回值的作用

main 函数的返回值用于说明程序的退出状态。如果返回 0,则代表程序正常退出;返回其它数字的含义则由系统决定。通常,返回非零代表程序异常退出。下面我们在 winxp 环境下做一个小实验。首先编译下面的程序:

int main( void )
    {
        return 0;
    }

然后打开附件里的“命令提示符”,在命令行里运行刚才编译好的可执行文件,然后输入“echo %ERRORLEVEL%”,回车,就可以看到程序的返回值为 0 。假设刚才编译好的文件是 a.exe ,如果输入“a && dir”,则会列出当前目录下的文件夹和文件。但是如果改成“return -1”,或者别的非 0 值,重新编译后输入“a && dir”,则 dir 不会执行。因为 && 的含义是:如果 && 前面的程序正常退出,则继续执行 && 后面的程序,否则不执行。也就是说,利用程序的返回值,我们可以控制要不要执行下一个程序。这就是 int main 的好处。如果你有兴趣,也可以把 main 函数的返回值类型改成非 int 类型(如 float),重新编译后执行“a && dir”,看看会出现什么情况,想想为什么会出现那样的情况。顺便提一下,如果输入 a || dir 的话,则表示如果 a 异常退出,则执行 dir 。

5. 那么 int main( int argc, char *argv[], char *envp[] ) 呢?

这当然也不是标准 C/C++ 里面定义的东西!char *envp[] 是某些编译器提供的扩展功能,用于获取系统的环境变量。因为不是标准,所以并非所有编译器都支持,故而移植性差,不推荐使用。




=============================================================================================

如果您觉得我不够权威,那么就让 C++ 之父 Bjarne Stroustrup 来说服您吧!

请点击进入 我可以写"void main( )"吗?


=============================================================================================
分享到:
评论

相关推荐

    C、C++语言误区之:voidmain().pdf

    `void main()`不符合C或C++的规范,因为它没有指定返回类型,而标准规定`main()`函数必须返回`int`类型,以便系统(通常是操作系统)能够检测到程序的运行状态。在某些编译器(如g++3.2)中,`void main()`将导致...

    C/C++ 常见误区

    【C/C++常见误区详解】 在C/C++编程中,遵循标准和良好的编程习惯至关重要,因为这直接影响到代码的可读性、移植性和维护性。以下是一些常见的误区及其解释: 1. **头文件包含误区**:在C/C++中,通常推荐使用`<>`...

    C语言难点分析整理

    67. C/C++ 误区一:void main() 373 68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383...

    基于C/C++ 常见误区详解

    在C/C++编程中,有一些常见的误区需要程序员们特别注意,以避免在开发过程中遇到问题。以下是关于这些误区的详细解释: 1. C++与C的关系:C++并不是C的升级版,它们是两种独立的语言,各有自己的标准委员会。C++98...

    C-C++ 常见误区

    在深入探讨《C-C++ 常见误区》这一主题之前,我们首先应当明确C与C++之间的关系及其发展脉络。C++并非C语言的简单扩展,而是基于C语言的一种全新的编程语言,由Bjarne Stroustrup于1983年在贝尔实验室创建。C++在C的...

    免费下载:C语言难点分析整理.doc

    C/C++ 误区一:void main() 这部分解释了为什么不应该使用`void main()`。 ### 68. C/C++ 误区二:fflush(stdin) 这部分解释了`fflush(stdin)`的不正确使用。 ### 69. C/C++ 误区三:强制转换 malloc() 的返回值 ...

    高级C语言 学完C语言来看这个绝对收获

    C/C++误区一:voidmain() C++标准规定主函数应声明为`int main()`。 #### 64. C/C++误区二:fflush(stdin) `fflush(stdin)`通常用于清除标准输入流,但这并不是标准C/C++的一部分。 #### 65. C/C++误区三:强制...

    gcc和g++的区别

    **误区一:gcc只能编译C代码,g++只能编译C++代码** 实际上,`gcc`和`g++`都能够处理C和C++代码。它们之间的主要区别在于默认处理文件的方式: - 对于后缀为`.c`的文件,`gcc`将其视为C代码,而`g++`将其视为C++...

    高级C语言.PDF

    1. C 语言中的指针和内存泄漏 ............................................................................................................. 5 2. C语言难点分析整理 ..........................................

    C语言函数参数的传递详解

    ### C语言函数参数的传递详解 #### 一、引言 在编程中,函数是非常重要的概念,它不仅可以提高代码的复用性,还能使程序结构更加清晰。在使用函数时,经常会涉及到参数的传递问题。对于不同的编程语言,参数传递的...

    数组与指针区别(很全面)

    本文旨在澄清关于数组名是否等同于指针这一常见的误区,并通过具体的代码示例来深入探讨数组和指针之间的关系及其差异。 #### 二、数组与指针的基本概念 1. **数组**: - 数组是一系列相同类型的数据项的集合。 ...

    srand和rand简介.docx

    《srand和rand在C/C++中的应用及原理》 `srand`和`rand`是C/C++编程语言中用于生成随机数的两个关键函数,它们在诸多领域,如模拟、游戏开发、加密等有着广泛的应用。理解这两个函数的工作原理和正确使用方式对于...

    2021-2022计算机二级等级考试试题及答案No.4857.docx

    25. 方法定义:在Java中,正确的方法定义应该返回类型与返回值匹配,A选项中返回类型不匹配,B和D选项不能在void方法中使用返回值,只有C选项是正确的。 以上内容详细解释了计算机二级等级考试中涉及的各种知识点,...

    2021-2022计算机二级等级考试试题及答案No.4240.docx

    - **详细解析**:一个工作人员可以使用多台计算机,同时一台计算机也可以被多个人使用,这种关系是典型的多对多关系。在关系数据库中,处理多对多关系通常需要引入一个关联表。 #### 19. 设置Bean属性值的正确方法 ...

    Java编写中容易搞错的一些东西

    在Java中,`native` 关键字用于标记一个方法是本地方法,意味着该方法的实际实现是在其他语言中,通常是C或C++。`native` 方法不需要提供具体的方法体,而是用一个分号 `;` 来代替大括号 `{}`,表明这是一个声明而非...

Global site tag (gtag.js) - Google Analytics