C语言的main函数的几种写法

yumo6662个月前 (07-03)技术文章10

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;
}
}

相关文章

C语言入门指南

当然!以下是关于C语言入门编程的基础介绍和入门建议,希望能帮你顺利起步:C语言入门指南一、什么是C语言?C语言是一门通用的高级程序设计语言,由Dennis Ritchie在20世纪70年代开发,被广泛...

使用C语言写一个&quot;Hello, World!&quot; 程序

默认您已搭建好语言的开发运行环境编写代码使用文本编辑器(如Notepad++)创建一个新的源文件,扩展名为.c,并输入如下内容到文件中,将文件保存为 hello.c:#include <stdi...

编译器动手实践之:实现C语言函数定义的语法解析

C语言是一种面向过程的语言,面向过程是指,将实现一个逻辑功能的代码集中到一起,每次需要使用的时候,再调用这些代码集合,这种代码集合就是函数。写C语言其实就是写一个个函数,因此对函数实现的语法解析是C语...

如何构建一个 C 语言编译环境

C语言是一种通用的编程语言,它是由Dennis Ritchie于20世纪70年代初在贝尔实验室开发的。C语言的设计目标是提供一种结构化、高效、可移植的编程语言,以支持系统编程和应用程序开发。C语言广泛...

C语言之Makefile

以下是如何使用 Makefile 编译C语言代码的详细教程,适合初学者理解其核心概念和操作步骤。一、为什么需要 Makefile?当项目包含多个源文件(如 .c 和 .h)时,手动逐个编译效率低下且容...