嵌入式--main函数是一个什么样的函数
朱有鹏
1、 main函数返回值
1.1 普通函数的返回值
在C语言中,我们定义一个函数的时候,一般都是给函数设计了输入和输出,函数的形参是函数的输入,返回值是函数的输出。
如程序8.2所示,我们定义了一个sum函数,在主函数中我们调用sum函数,它完成了一个和运算,并将和的结果返回给a,此时a的值就是函数sum运算的结果。
int sum(int a, int b)
{
return a+b;
}
void main(void)
{
int a = 0, b = 3, c = 0;
a = sum(b, c); (1)
printf("a = %d.\n", a);
}
程序 8.2 函数的返回值
看到这里大家应该明白了,当我们需要函数对外输出数据(实际上就是函数运行的结果)就需要函数返回值。也就是说,函数被另一个函数调用,返回值作为函数的值返回给该函数调用者。应当注意的是,在函数中我们用return语句返回函数的返回值。函数体中如果遇到了return语句,那么函数就会停止运行,返回结果值。如上程序中,我们将sum函数修改如下
int sum(int a,int b)
{
if(a >b)
{
return a-b; (1)
}
else
{
return b-a; (2)
}
return a+b; (3)
}
上述代码中,如果a>b 执行(1),否侧执行(2)。这里的(3)永远都不会执行,因为函数执行到(1)、(2)就已经结束了。
在C语言函数中使用return 语句时应当遵守以下规则:
(1)如果函数指定返回类型为void,则不应该加入return语句。
(2)如果函数指定除void之外的其他返回类型,那么必须在函数中加入一条return语句。
1.2、main函数的返回值
我们知道main函数是特殊的,因为C语言规定了main函数是整个程序的入口,其它的函数只有直接或间接被main函数调用才能被执行。C语言的设计原则就是把函数作为程序的构成模块,main函数就像是我们搭积木的主体,函数就是一个个积木。C语言的程序总是从main()函数开始执行的。
在最新的C99标准中,main()函数只有两种定义,分别是
int main(void) //不带参数形式 int main(int argc, char *argv[]) //带参形式
{ {
... ...
return 0; return 0;
} }
带参形式还有一种写法
int main(int argc, char **argv)
{
...
return 0;
}
通过前面指针的学习,我们知道其实这两种带参的作用是一模一样的。 int说明了main()函数的返回值类型,函数名后面的圆括号包含了传递给函数的信息。void表示没有给main函数传参数。接触过单片机的同学,看到这里可能会有疑问,在单片机的C语言代码中,main()函数常常以void main(void)的形式出现。这个是因为单片机的编译器是允许这种形式出现的,单片机中的C并不是标准的C99。在实际项目中,建议大家还是使用标准的形式,这样做的好处是:当你把程序从一个编译器移到另一个编译器时,照样能正常工作。
从前面我们知道main()函数的开始意味着整个程序开始执行,main()函数的结束意味着整个程序的结束。main()函数从某种角度来讲代表了我们当前这个程序,或者说代表了整个程序。谁执行了这个程序,谁就调用了这个程序中的main()函数。main()函数的返回值是int类型数据,通常我们在main()函数最后 return 0,0就是main函数的返回值,返回0说明我们程序正常执行,程序运行结束,返回非0说明程序异常。所以main()函数中返回值的意义,不仅仅是一个返回值,还说明结束程序、程序是否运行正常。
1.3、谁执调用了main函数
在linux C开发中,我们可以通过在linux中的命令行中去./xx执行一个可执行程序,也可以通过shell脚本来调用执行一个程序,还可以在程序中去调用执行一个程序(fork exec)。虽然我们有多种方法去执行一个程序,但是本质上是相同的。linux中一个新程序的执行本质上是一个进程的创建、加载、运行、消亡。linux中执行一个程序其实就是创建一个新进程然后把这个程序丢进这个进程中去执行直到结束。linux中进程都是被它的父进程fork出来的。命令行本身就是一个进程,在命令行下通过./xx方式执行一个新程序,其实这个新程序是作为命令行进程的一个子进程执行。总之一句话:一个程序被它的父进程所调用。main()函数也理所应当的被它的父进程调用。main函数的返回值返回给调用这个函数的父进程。父进程调用子进程来执行一个任务,然后子进程执行完后通过main函数的返回值返回给父进程一个答复。这个答复一般是表示子进程的任务执行结果完成了还是错误了。
2、argc、argv与main函数的传参
从前面的知识,我们知道main()函数的参数是由调用main函数所在的程序的父进程专递的,并且它接收main的返回值。在linux C中,main()函数可以传参,也可以不传参,int main(void)这种形式就表示我们没有给main传参。但有时候我们希望程序具有一定的灵活性,所以选择在执行程序时通过传参来控制程序的运行,达到不需要重新编译程序就可以改变程序运行结果的效果。
主函数main()的第一个参数是命令行中的字符串个数,即程序运行的时候给main()函数传递的参数个数。
一般的(不是必须的),这个int参数被写成argc(argument count 变量个数)。现在你是否明白了为什么这个形参会有这么特别的名字了吧。难的不会,只是简单的东西没有学好。了解了这些细节,你会比别人学得更好。第二个参数是一个指向字符串的指针数组。命令行中的每一个字符都被存储到内存中,并且分配一个指针指向它。一般的,我们把这个数组写成argv(argument value)。argv[0]就是我们给main函数的第一个传参,第一个传参就是程序的名字,argv[1]就是传给main的第二个参数····
现在我们来看一个例子,如程序8.2所示
#include
#include
// 通过给main传参,让程序运行的时候去选择执行哪个从而
//得到不同的执行结果
int main(int argc, char *argv[])
{
int i = 0;
printf("main函数传参个数是:%d.\n", argc);
for (i=0; i
{
printf("第%d个参数是%s.\n", i, argv);
}
return 0;
}
编译,在命令行中输入 ./a.out 0 回车,程序运行的结果如下:
main函数传参个数是:2.
第0个参数是./a.out.
第1个参数是0.
在main传参我们需要注意一下几点,否侧容易出现问题。
1.main()函数传参都是通过字符串传进去的。
2.main()函数只有被调用时传参,各个参数(字符串)之间是通过空格来间隔的。
3.在程序内部如果要使用argv,那么一定要先检验argc。
摘取自书籍【朱有鹏c语言内核深度解析】
百度搜索“朱有鹏物联网大讲堂”,可以在官网看免费视频