美文网首页
[C语言]你真的了解C语言吗之main函数(一)

[C语言]你真的了解C语言吗之main函数(一)

作者: IAMLIUBO | 来源:发表于2019-03-22 11:38 被阅读0次

有时候学过的知识反过头来再看看总会有新理解,这可能就是所谓的温故而知新吧,最近读了一篇文章,觉得说的很对,感兴趣的可以读一下。

http://norvig.com/21-days.html​norvig.com

就像文章中说的一样,现在的人们都太急于求成,各种“XX天XXX语言从入门到大神”,大家有没有想一下,这现实吗?文章不是很长,建议大家都去看一下。

能够点进来看这篇文章的应该都是懂C语言的,那么相信大家也都写过很多代码了,那么我们先来看一下下面这几种main函数的定义,哪一个是正确的哪一个是错误的。

main()

main(void)

main(int argc,char *argv[])

main(int argc,char **argv)

void main()

void main(void)

void main(int argc,char *argv[])

void main(int argc,char **argv)

int main()

int main(void)

int main(int argc,char *argv[])

int main(int argc,char **argv)

相信大家或多或少都见过或这写过上面这这些main函数中的某一种,那么大家对这个C语言中最重要的一个函数有多少了解呢?有没有深究过该怎样写和为什么这样写呢?其实讲实话,我之前也是知其然不知所以然,因为觉得会用就好了,为什么还要深入的去了解呢?所以现在还是菜鸟的一个原因吧。。。之所以写这篇文章主要还是最近在做Linux程序开发,这技术水平不到可不就得深入去了解一番嘛,作为一个菜鸟码农就得不断去学习不断去充实自己。

其实上面的这几种main函数的定义在某种意义上来说是都是正确的,因为在不同的标准下编译都是可以编译通过的,但是这不代表可以编译通过我们就可以认为是正确的写法,既然有标准我们就要根据标准去写,毕竟有了规则大家才可以写出更好的代码,下图是C11标准中对main函数的说明,大家可以看一下。

image

<figcaption style="margin-top: 0.66667em; padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">C11-main</figcaption>

下面我们来实际测试一下,看看编译器在不同标准下如何处理上面的几种情况,这里的测试环境是Ubuntu 16.04 & gcc 5.4.0,第一个测试代码:

#include <stdio.h>
//不声明main函数类型
//main() 与 main(void) 是等价的
main(void){
        printf("hello world!\r\n");
}

image

可以看出在C99与C11标准下编译会提示一个警告,说默认返回类型是int类型,但是在比较老的C90标准下是可以编译通过和运行的,我们再继续测试下一个:

#include <stdio.h>
//声明main函数类型为void
//void main() 与 void main(void) 是等价的
void main(void){
        printf("hello world!\r\n");
}

image

可以看出在三种标准之下是都可以编译通过的,但是这并不代表这就是正确的,我们再来看一下C11标准中是怎么讲函数的返回值的:

image

我们可以这样想,函数的返回值是判断这个函数执行是否成功的一个标志,就像你自己写某一个子函数时,不同的情况可能会对应不同的返回值,从而做出不同的处理,我们写一个程序最终是要被系统调用的,那我们定义一个void类型,系统该如何判断调用是否成功呢?所以这种写法是禁止的,不推荐的,而且这种写法在任何一个标准都没有声明过,我们继续测试下一个:

#include <stdio.h>
//声明main函数类型为int
//int main() 与 int main(void) 是等价的
int main(void){
        printf("hello world!\r\n");
}

image

可以看到我们这里虽然声明了int类型,却没有在程序中return一个返回值,但是在三种标准下都可以编译通过并执行,这是为什么呢?其实在前面图中有说明,如果我们没有写return语句,程序是会在执行到“}”时默认返回0,0表示程序执行成功,所以正确的写法应该如下:

#include <stdio.h>
//声明main函数类型为int
//int main() 与 int main(void) 是等价的
int main(void){
        printf("hello world!\r\n");
     return 0;
}

在这几个测试代码中我们测试了不同类型的main函数在不同的标准下编译,我们也查看了标准中是推荐怎样写的,所以我们以后写的时候还是要根据标准来,有时候有一个良好的代码规范在合作开发中是非常必要的。

但是这不是本篇文章要讨论的重点,之所以写这篇文章是因为最近写的东西需要处理一些命令行参数,相信大家应该都接触过命令行参数吧,下面就给大家举个简单的栗子:

gcc -std=c11 -o hello hello.c

没错这就是我们刚刚用过的一条命令,gcc 是可执行文件,就像我们前面编译好的hello一样,是可以直接执行的,但是后面跟那么多参数是做什么的呢?其实简单来说就是根据不同的参数执行不同的命令,就像std(standard)参数一样,通过我们给出的不同参数执行不同标准下的编译标准。

那么这些参数是怎样传递进去的呢?这里就不得不提我们的main函数了,大家都知道main函数是整个程序的入口,程序的执行就是从这里开始,所以当然main函数就是我们的参数入口了,相信仔细阅读的你肯定在前面的图片中也有所发现了,这里我们再来看一下:

image

第一种就是不带参数的,第二种是带参数的,我们先上个简单代码:

#include <stdio.h>
/**
 *@author imliubo
 *@brief  main函数传参测试代码
 *@param  argc    传入的参数个数,argc>=1
 *@param  *argv[] 传入的参数的值,argv[0]=当前执行的程序名
**/
int main(int argc,char *argv[]){

  printf("argc:\t argv:\r\n");

  for(int i=0;i < argc;i++){
    printf("%d\t %s\r\n",i,argv[i]);
  }

 printf("argc total:%d\r\n",argc);
  return 0;
}

我们先来看一下不加任何参数运行会打印什么:

image

可以看到我们不加任何参数时,argc跟argv的值都是有变化的,因为默认的第一个参数是当前程序的名(包含路径),参数总个数为1,我们再来看看我们加几个参数会打印什么:

image

可以看到我们在命令行中的四个参数都打印出来了,加上默认的一共5个一个也没有少,参数与参数之间是通过空格区分的(如果想将两个参数合并成一个可以通过加上引号实现),那么我们该怎样利用这些参数呢?一个好的程序是可以配置的,不同参数会有不同的运行结果,那么我们写一个通过参数控制打印不同字符的程序,这里我们用最简单的方法去实现:

#include <stdio.h>
#include <string.h>
/**
 *@author imliubo
 *@brief  main函数传参测试代码
 *@param  argc    传入的参数个数,argc>=1
 *@param  *argv[] 传入的参数的值,argv[0]=当前执行的程序名
**/
int main(int argc,char *argv[]){

  for(int i=0;i < argc;i++){
    if(strcmp("imliubo",argv[i])==0){
      printf("Hi %s,how was going?\r\n",argv[i]);
    }
    if(strcmp("xiaomei",argv[i])==0){
      printf("What a beautiful girl!\r\n");
    }
  }
  return 0;
}

image

可以看出我们通过配置不同的参数,程序是不同的执行的结果,当然这是一种菜鸟程序员的写法,通过不断的比较去执行不同的代码,加入我们再在这个参数前面加上一个带有"-"修饰的字符,处理起来就要麻烦的多了,但是这种麻烦的问题肯定不只有我们才发现,所以已经有大神给我们写好工具了。

平常我们在处理很多繁杂的命令行参数时都会使用getopt()函数,比如像下面这条命令:

sudo ./nuwriter -m nand -d NUC972DF62Y.ini -t uboot -a 0x200 -w /home/imliubo/NUC972/WORKSPACE/COIDEA/BSP/03.uboot/nand_spl/u_boot_spl.bin -v

如果我们自己去解析这条命令中的参数,费时间不说,其中的逻辑还那么复杂,所以我们一般都是使用getopt()函数去解析,本篇文章就先到这,我会在下一篇文章中跟大家讨论一下。

文章难免有错误,如果有不对之处,还请及时指出我好及时改正。

欢迎关注我的专栏,我会不定期分享一些开发经验。

相关文章

  • [C语言]你真的了解C语言吗之main函数(一)

    有时候学过的知识反过头来再看看总会有新理解,这可能就是所谓的温故而知新吧,最近读了一篇文章,觉得说的很对,感兴趣的...

  • [C语言]你真的了解C语言吗之main函数(二)

    在上篇文章中我们简单讨论了一下main()函数,了解了一下正确的写法,在文章的最后我们简单分析了一下参数是怎么传递...

  • python、main函数和argv参数

    笔者学习和使用过的语言中:C语言,C++语言,C#语言,Java语言都时有main函数在的,main是程序执行的起...

  • 2018-08-29日常C笔记

    C语言初学笔记 C语言程序是由函数组成的C语言程序启动时,系统就会自动调用名字叫main的函数C语言规定了函数定义...

  • VC 在调用main函数之前的操作

    在C/C++语言中规定,程序是从main函数开始,也就是C/C++语言中以main函数作为程序的入口,但是操作系统...

  • C语言 main()函数

    C语言 main()函数 C语言main函数的完全格式是 argc: 是执行程序时命令行参数个数,需要注意,程序本...

  • 01-Go语言与C语言的异同

    Go语言程序组成 和C语言一样,Goa语言也是由众多函数组成 和C语言一样,程序运行会自动调用叫做main的函数 ...

  • 命令行参数

    C语言中的命令行参数在C语言中main函数可以接收两个参数int main(int argc, const cha...

  • go 语言第三节课

    命令行参数 1.C语言中的命令行参数在C语言中main函数可以接收两个参数int main(int argc, c...

  • C语言程序可以没有main函数

    学习C语言的同学都知道,每个C程序要有一个main函数,程序从main函数开始执行,在main函数中结束。但事实上...

网友评论

      本文标题:[C语言]你真的了解C语言吗之main函数(一)

      本文链接:https://www.haomeiwen.com/subject/jmslvqtx.html