你真的了解main函数吗?

简介: 你真的了解main函数吗?

我们每写一个C程序或者C++程序,都需要敲下这样的一个函数名main,但是为什么要有main函数?main函数真实的面容又是什么样呢?


为什么要有main函数或者main函数的作用是什么?前两天一个初学者问我问题,说他的代码报错了,没法运行,然后我定睛一看,整个代码没有main函数,所以报错了!

image.png


这个问题对于已经入门的人来说,可能不会犯,但是对于新手来说,他感觉自己照着书上的代码写的,为什么连编译都不行呢?很是郁闷啊!!并且他并不理解,为什么写了main编译就通过了,但是我还是运行不出来想要的结果呢(main函数中没有调用他写的函数,也没有执行什么其它的操作),所以main函数究竟是干什么的?

我们平时见到的main函数大致是这个样子的:

int main()
{
  ........
  return 0;
}
void main()
{
  ........
  return;
}

main函数是C语言或者C++程序的一个入口,我们需要编译生成一个可执行项目的过程中会经过好几个阶段,而在生成的可执行文件中,main函数就是它的入口,就好比我们需要盖一个房子,为了我们进出方便,肯定是有一个大门,房子里面有厨房、洗手间、卧室、书房等等的细节,但是进入房子的门只有一个!而我们想要进到房子里面去睡觉、上洗手间,需要先打开房门,对于一个exe程序来说,main函数就是它的房门,没有房门,完全密闭的一个房子,里面不管有多么的精致,你也无法享受!通过这道房门,在房子里面装上各种功能器件,那就可以享受了!所以main函数是不可或缺的程序入口,也是一切的开始。


但是我们是否又见过这样的main函数呢?

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

嗯?main函数居然还有参数?为什么我从来没见过main函数的参数啊?这些参数我们怎么获得?那参数又是怎么传到程序中的呢?


确实!main函数是有参数的,你没有看错!我来解释一下这三个参数:

第一个参数是一个整型,其中包括的是命令行参数的个数,第二参数是一个二维的char型指针,存放命令行参数字符串,第三参数是二维的char型指针,存放环境变量。那我们怎么获得命令行参数呢?写一个简答的示例代码:

int args_parse(int argc, char** argv)
{
  //argv[0] 是当前进程名
  int i = 0;
  while (i < argc)
  {
  printf("%s\r\n", argv[i]);
  i++;
  }
  return 0;
}
int main(int argc, char** argv, char** envp)
{
  args_parse(argc,argv);
  return 0;
}


我在函数args_parse中定义了两个参数,然后在main函数传参就直接把main函数参数传入进去,这些参数都是程序从外部获取的,我们只需要取出即可。当我们没有输入任何的命令行参数的时候,这个程序会输出当前进程名,因为命令行参数的第一参数是当前进程名:

image.png

使用命令行参数有什么作用?使用命令行参数可以控制程序的执行,我们的程序可能实现了很多的功能,就比如图书管理系统,有增加图书,查书籍等等不同的功能,这些功能有自己的代码段,我们如何可以定位去执行哪一段代码呢?这时候就可以利用参数的方式,我们在命令行传入的参数,就好比一个指令,在程序内部设计指令识别,然后对不同指令解析去执行不同的功能模块。那我们怎么传入命令行参数呢?


我们可以从cmd传入,将当前可执行文件完整路径输入,接着随便输几个字符串,然后看看效果,举例:

image.png

我们在此处可执行文件完整路径后面输入的,都是命令行参数!那么新的问题来了,如果我代码有问题,想调试一下,但是调试过程中没法输入命令行参数啊,毕竟命令行参数是在main函数执行之前就传入的,这时候怎么办呢?我们拿vs举例:

image.png

右键选择当前项目,点击属性,然后点击调试–>命令行参数,然后输入就可以了:

image.png

动态操作流程:

image.png

每个进程都有一个与它相关的环境块,在进程地址空间分配时候会为环境变量分配一块内存,每个字符串的第一部分是一个环境变量的名称,后跟一个等号,等号之后是希望赋给此变量的值。这种字符不能作为环境变量使用。那么怎么获取环境变量呢?

void envp_parse(char** envp)
{
  int i = 0;
  char** Travel = envp;
  while (NULL != Travel)
  {
  if (NULL == *Travel)
  {
    printf("Envp Over!!!\r\n");
    return;
  }
  else
  {
    printf("%s\r\n", *Travel);
  }
  Travel++;
  }
}
int main(int argc, char** argv, char** envp)
{
  //args_parse(argc,argv);
  envp_parse(envp);
  getchar();
  return 0;
}

运行效果部分图:

image.png

有关main函数的简单科普就到此结束啦!下篇博文与各位再见面喽!!!



目录
相关文章
|
自然语言处理 API Swift
Qwen1.5开源!魔搭最佳实践来啦!
近几个月来,通义千问团队一直在努力探索如何构建一个“好”的模型,同时优化开发者体验。就在刚刚,中国新年前夕,通义千问团队分享了Qwen开源系列的下一个版本,Qwen1.5。
|
JSON 前端开发 Java
Spring WebFlux使用函数式编程模型构建异步非阻塞服务
Spring WebFlux使用函数式编程模型构建异步非阻塞服务
537 0
|
前端开发 数据可视化 安全
82.7K star!大气炫酷UI开源项目,超级火!
shadcn/ui 是一款基于 Radix UI 和 Tailwind CSS 构建的现代化 UI 组件库,专为追求设计品质与开发效率的开发者打造。不同于传统组件库,它提供完全可定制的组件代码模板,让开发者既能享受开箱即用的便利,又能保持对设计系统的完全掌控。
692 13
|
设计模式 Java 程序员
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
本系列文章聚焦于面向对象软件设计中的设计模式,旨在帮助开发人员掌握23种经典设计模式及其应用。内容分为三大部分:第一部分介绍设计模式的概念、UML图和软件设计原则;第二部分详细讲解创建型、结构型和行为型模式,并配以代码示例;第三部分通过自定义Spring的IOC功能综合案例,展示如何将常用设计模式应用于实际项目中。通过学习这些内容,读者可以提升编程能力,提高代码的可维护性和复用性。
3756 1
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
|
Kubernetes 容器
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
731 0
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的“爱相连”儿童慈善管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的“爱相连”儿童慈善管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
181 3
|
编译器 C++
C++新特性 内联命名空间
C++新特性 内联命名空间
231 0
|
前端开发 API 网络架构
React-Router-URL参数
React-Router-URL参数
225 0
|
算法
我明白了,leetcode91题
91题**解码方法**的难度属于中等,但其涉及到的知识并不少呢,斐波那契、备忘录剪枝、动态规划等等,除了题解之外,我也会深入浅出的讲解这些知识点,文章末尾我还会使用 正则 + 斐波那契的写法来解题,我们一起来看看。
270 0
我明白了,leetcode91题