C/C++语言误区void main( )
很多人甚至市面上的一些书籍,都使用了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(《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 。
int main( int argc, char *argv[], char *env[] ) 也不是标准C里面定义的东西~char *env[]是某些编译器提供的扩展功能~用于获取系统的环境设定~因为不是标准~故而移植性差~不推荐使用
本文版权归 蚂蚁的 C/C++ 标准编程 以及 作者 antigloss 共同所有,转载请注明原作者和出处。谢谢。
C/C++语言误区void main( )的更多相关文章
- 「C语言」int main还是void main?
从大一入学刚接触C到现在已满7个月了,虽然刚开始就知道```int main```才是标准的写法,但一直没有深刻理解为什么不能用```void main```而必须使用```int main```. ...
- 关于void main()的误区
很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的.C/C++ 中从来没有定义过void main( ) .C++ 之父 Bjarne Stroustrup 在他的主页上的 ...
- int main()还是void main()
按照新的C99标准,即使函数本身没有定义返回值,编译器也会加上,以返回给激发程序,运行状态.很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的.C/C++ 中从来没有定义过 ...
- C语言编程漫谈——main函数
写在前面 促使我写这篇文章是因为我这几天找了几个一样是大三的同学,与我相同专业相同方向(物联网)的人,除了@小胡同的诗,基本没有什么其他人会现在看起来很简单的编程题目了.问了一下其他同学,他们大部分都 ...
- C/C++ 下的void main()
很多人甚至市面上的一些书籍,都使用了void main( ),其实这是错误的.C/C++ 中从来没有定义过void main( ).C++之 父 Bjarne Stroustrup在他的主页上的 FA ...
- java里面的public static void main(String[] args)
package com.java_1; public class Hello { public static void main(String[] args){ System.out.println( ...
- java中public static void main(String[] args)中String[] args代表什么意思?
这是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法.跟C语言里面的main()函数的作用是一样的.只有有main()方法的java程序才能够被java虚拟机欲行,可理解为 ...
- JAVA:从public static void main(String args[])開始
我们都知道当你要执行一个JAVA文件的时候必需要有一个main函数. 这是为什么呢? 跟C语言的道理一样,当你执行一个文件的时候.你必需要有一个入口函数或者入口地址,在C里面是main函数.相同的在J ...
- void main() && int main()
C/C++ 中从来没有定义过void main( ) .C++ 之父说过: The definition void main( ) { /* ... * / } is not and never ha ...
随机推荐
- Java网络方面
最近在面试 有些概念懂 但是需要梳理一下 借着面试看看自己会多少. 1.网络编程的同步 异步 阻塞 非阻塞? 同步:函数调用在没有得到结果之前,不返回任何结果: 异步:函数调用在没有得到结果之前,不返 ...
- 在Docker中启动Cloudera
写在前面 记录一下,一个简单的cloudera处理平台的构建过程和一些基本组件的使用 前置说明 需要一台安装有Docker的机器 docker常用命令: docker ps docker ps -a ...
- 基于Docker搭建大数据集群(二)基础组件配置
主要内容 jdk环境搭建 scala环境搭建 zookeeper部署 mysql部署 前提 docker容器之间能免密钥登录 yum源更换为阿里源 安装包 微云分享 | tar包目录下 JDK 1.8 ...
- hadoop之mapreduce详解(优化篇)
一.概述 优化前我们需要知道hadoop适合干什么活,适合什么场景,在工作中,我们要知道业务是怎样的,能才结合平台资源达到最有优化.除了这些我们当然还要知道mapreduce的执行过程,比如从文件的读 ...
- 在vue的mounted下使用setInterval的误区
1. vue对象的生命周期 1). 初始化显示(只执行一次) * beforeCreate() * created() * beforeMount() * mounted() 2). 更新状态(可执行 ...
- java架构之路-(spring源码篇)springIOC容器源码解析(上)
我们这次来叭叭一下Spring的源码,这次博客主要来说说Spring源码,先粗略的撸一遍,下篇博客选几个重点去说,由于过于复杂,我也是看了一点点,我们先来过一遍源码,然后上流程图,最后我们再回头总结一 ...
- 【Oracle】SQL语句优化
(1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最 ...
- mapper插入时显示中文
可能是jdbc url需要加characterEncoding=utf-8,例 jdbc:mysql://localhost:3306/smbms?characterEncoding=utf8
- Vue入门教程 第一篇 (概念及初始化)
注:为了本教程的准确性,部分描述引用了官网及网络内容. 安装Vue 1.使用npm安装vue: npm install vue 2.下载使用js文件: https://vuejs.org/js/vue ...
- vue图片点击放大预览
第一种:viewerjs使用介绍(PC.移动端都兼容) 1.先安装依赖 npm install v-viewer --save 2.main.js内引用并注册调用 //main.js import V ...