网站首页 > 技术文章 正文
main函数即为主函数,C程序总是从main()函数开始执行的。main函数是整个C程序的执行入口,一个程序想要运行起来,必须指定main函数。各种资料和书籍对main函数的写法各有不同,甚至很多的写法都有误区,本文整理了常见的mian函数写法,并逐一测试说明。
注意:以下程序均在GCC9.2环境下编译运行,不同的编译器编译结果并不一定相同。
标准版本
C89/C99/C11标准文档中只提供了两种main函数的写法:
int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }
C99规定:main函数必须有返回值,而且必须是int 类型的,main函数return 0表示函数正常退出,否则表示错误退出,如果没有return语句,编译器自动在目标上添加return 0。
如果把main函数当成普通函数那么除了函数名main不可变,那么其他都有可以变,返回值类型,参数列表,返回值这三种搭配会产生各种形式。
无参main函数
样式一:int main(void){/* ... */}
样式二:void main(void){/* ... */}
样式二:main(void){/* ... */}
样式一不必多说,那么其他两个是怎么出现的?样式二这种常见于老旧的教材,我记忆中那会谭浩强的书里就有这种写法。目前不少的编译器是能够编译通过的,但是这是编译器的处理并不是标准中的定义,甚至在C99之后明确规定这种就是错误写法!样式三不写返回值类型在C89标准中允许,C语言第一版中只有int一种类型,没有char,long,float等,既然只有一种类型,那么就可以不写,后来的改进版为了兼容以前的代码便规定:不明确标明返回值的,默认返回值为int,也就是说样式三等同于样式二。虽然可以编译,但在C99标准中要求编译器至少给 main() 这种用法警告,强烈不建议这么写!
使用以上的形式输出Hello World结果如下:
样式四:int main(){/* ... */}
样式五:void main(){/* ... */}
样式六:main(){/* ... */}
样式四到样式六对应着样式一到样式三,唯一不同在于里面的void省去了,很多人觉得这个应该和void一样的,都是表示不带参数的意思,但实际上并不是!在C语言中func()表示的是参数类型,数目不确定,并且可以重新对它的完整参数类型和个数重新声明。但是func(void)则完全限制了不允许任何参数,即使重新声明,也不能改变。
使用func():
void func(){
printf("func()\n");
}
int main(void){
func();
func(1,2);
func(1,'a');
func(1,"abc");
return 0;
}
使用func(void):
void func(void){
printf("func()\n");
}
int main(void){
func();
func(1,2);
func(1,'a');
func(1,"abc");
return 0;
}
使用样式四到样式六输出Hello World结果与样式一到样式三一致,图略。
有参main函数
样式一:int main(int argc, char *argv[]){/* ... */}
样式二:void main(int argc, char *argv[]){/* ... */}
样式三:main(int argc, char *argv[]){/* ... */}
样式四:int main(int argc){/* ... */}
样式五:void main(int argc){/* ... */}
样式六:main(int argc){/* ... */}
样式七:int main(int argc, char *argv[], char *envp[]){/* ... */}
样式八:void main(int argc, char *argv[], char *envp[]){/* ... */}
样式九:main(int argc, char *argv[], char *envp[]){/* ... */}
以上的各种形式中指针数组都可以使用二级指针替换:*argv[]->**argv,*envp[]->**envp.这里不一一列出来了。
标准的main函数中的参数最多有两个:第一个参数argc(argument count)是命令行中的字符串个数。第二个参数argv(argument value)是一个指针数组,一般程序名赋值给argv[0],从argv[1]开始对各个参数依次赋值。这里的参数可选,使用一个,使用两个都可以。
一个argc参数:
int main(int argc){
printf("%d",argc);
return 0;
}
两个标准参数:
int main(int argc,char *argv[]){
int i;
for ( i = 0; i < argc; i++){
printf("%s|",argv[i]);
}
return 0;
}
main函数还可以有第三个参数,用于获取环境变量,这种形式多源于编译器的扩展。但全局变量environ可以代替envp的作用,获取或者设置环境变量可以使用getenv或putenv,因此这种形式出现的很少。
三参数:
int main(int argc,char *argv[],char *envp[]){
int i;
for ( i = 0; i < argc; i++){
printf("%s|",argv[i]);
}
printf("\n");
int j=0;
while(envp[j]){
printf("%s\n",envp[j]);
j++;
}
return 0;
}
返回值
main函数的返回值最终会作为程序的退出状态,0表示函数正常退出,否则表示错误退出。这也是不推荐使用void作为返回值类型的原因,一旦声明为void,在程序退出后,想要获取其退出状态也就不可以了!如果main函数的最后没有写return语句的话,C99规定编译器要自动在生成的目标文件中加入return 0,表示程序正常退出。尽管省略return语句后,也能通过编译,但仍建议最好加上return语句,养成好习惯。
其他环境
在其他领域以上规则不尽然完全适用,单片机中使用void main(void)还是很常见的。很多低级单片机的资源有限,常见的比如51单片机,基本上不会使用系统的,一般就是裸跑, 编译器初始化后直接转到main运行,不会给main传任何参数。进入main里面做一些硬件初化后,一般会进入while的死循环保持运行,直到掉电,不需要返回值,所以经常可以看到void main(void)这样的代码。
51单片机点灯:
#include <reg52.h>
sbit LED=P1^0;
void main(void){
LED=0;
while(1){
LED=1;
}
}
猜你喜欢
- 2025-09-21 Python操作目录_python中目录的写法
- 2025-09-21 使用Redis如何实现查询附近的人?_redis查找
- 2025-09-21 嵌入式可测试性设计的威力!_嵌入式测试怎么样
- 2025-09-21 Redis命令执行过程_redis-cli执行命令
- 2024-08-05 爬虫|快手短视频爬取经验分享(python爬取快手视频)
- 2024-08-05 如何用C++程序抓出来文件中的某一列 (类似awk)?
- 2024-08-05 详解Python sys.argv(详解杭州亚运会会徽和口号)
- 2024-08-05 「C语言重点难点精讲」关键字精讲1
- 2024-08-05 如何高效阅读代码?Linux大神拍了拍你并教给你这三个步骤
- 2024-08-05 一文带你了解操作系统核心概念(操作系统核心的主要作用)
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)