一道看似简单却易错的C语言的main函数的参数题目(海康威视的面试题)

本文主要是介绍一道看似简单却易错的C语言的main函数的参数题目(海康威视的面试题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一道海康的面试题,C语言的main函数有几个参数(多选)

A:argc
B:envp
C:main
D:argv

正确答案是:ABD 

一般情况下,我们会认为是只有两个参数,因为从我们从第一次接触,基本看到的就一直是int argc,char *argv[]这样的形参,第一个参数argc是整型变量,第二个参数argv是指向字符串的指针数组,当然main函数也可以不写参数,这种情况比较少。

那么从实际给出的答案中,我们知道实际情况是还有一个指向环境变量的指针数组char *envp[] 

我们先来看下 int argc 这个我们知道,是统计命令行参数的个数:

#include <stdio.h>int main(int argc, char *argv[])
{printf("参数个数:%d\n", argc);for (int i = 0; i < argc; i++){printf("%s\n", argv[i]);}return 0;
}

 Windows环境:

>gcc test.c -o test
>test Hello China Great
参数个数:4
test
Hello
China
Great

Linux环境:

$ gcc test.c -o test
$ ./test Hello China Great
参数个数:4
./test
Hello
China
Great

可以看到上述的程序名test也当作了一个参数,所以我们获取参数,最好下面这样写:

#include <stdio.h>int main(int argc, char *argv[])
{while (argc-- > 1){printf("%s\n", *++argv);}return 0;
}

前面两个参数大家熟悉了,重点来看下环境变量envp这个指针数组,正确的写法如下:

#include <stdio.h>int main(int argc, char *argv[], char *envp[])
{int i = 0;while (envp[i]){printf("%s\n", envp[i++]);}return 0;
}

重新编译之后,Win和Linux中的截图如下:

可以看到显示了本地的环境变量,每个字符指针指向一条环境变量。

我们来了解下,这个main函数是怎么被调用的,首先会在加载时,启动一个_start函数,这个函数调用_libc_start_main函数,再去调用main函数的,也就是说,真正的入口函数应该是main被调用前的两个函数。
_start函数的作用主要就是调用__stack_init来初始化堆栈,调用__data_init来初始化全局变量,以及main函数和__exit_program退出程序,将控制权交给操作系统。
那么这个_libc_start_main也是程序入口,怎么理解呢?这个_start函数一般是在汇编中定义,操作系统加载程序的时候,控制权就交给_start函数,而_libc_start_main是C标准库中定义的(glibc),作用也是做一些初始化工作和调用main函数,这个函数是有编译器自动调用,跟程序员无关。
所以这里,我们来看下_libc_start_main函数的源码,当然这个内部函数跟操作系统和编译器有很大关系,代码大概如下:

int _libc_start_main(int (*main)(int, char**, char**), void (*exit)(void), void (*abort)(void), char** environ, void (*h)(void (*)(void)), void (*h_rt)(void (*)(void)), void (*thread_detach)(void)) {// 初始化C库libc_init();// 用户的main函数int result = main(argc, argv, environ);// 清理工作libc_cleanup();// 返回main函数结果return result;
}

这里我们可以看到,main函数的参数是三个,类型分别是int, char**, char**,函数体重自定义的main函数三个形参名称为argc, argv, environ,其中environ就是指向环境变量的指针数组,这样就解释了,main函数本质上是三个参数。
我们也可以看到一道看似简单的面试题,也可以引申出操作系统对于如何加载C程序的一些扩展知识。

这篇关于一道看似简单却易错的C语言的main函数的参数题目(海康威视的面试题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/247481

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

SpringBoot通过main方法启动web项目实践

《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring... 目录1. 启动入口:SpringApplication.run()2. SpringApplicat

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作