由main函数引发的深思
- main 函数在很多方面都比较特别,其中最重要的是每个 0+程序必须含有 main 函数,且 main 函数是(唯一)被操作系统显式调用的函数。
- 定义 main 函数和定义其他函数一样。定义函数必须指定 4 个元素:返回类型、函数名、圆括号内的形参表(可能为空)和函数体。main 函数的形参个数是有限的。本例中定义的 main 函数形参表为空。7.2.6 节将介绍 main 函数中可以定义的其他形参。
- 为什么C++ 程序必须含有一个main函数?
答:这是和操作系统的配合,因为操作系统启动一个c++程序,实际是启动c++运行时(c++ runtime system)。而 c++ 运行时(C++ runtime system)预设的就是调用main 函数。
而这里的C++ 运行时,就是由编译器生成到程序上面的。
操作系统调用main函数 被称之为唯一显式,那么怎么解释唯一?为什么是显式?
这里的本质还是和上面的一样,唯一是指这是唯一的一个在运行时中说明要调用的。
显式调用 是说 调用的方式是明确说明函数名称,而不是使用 指针 + 偏移量 的方式。1
函数的四元素是什么?
- 返回值、函数名称、形参、代码块也叫函数体
- 为什么main 函数的返回值类型必须是int ?
- 这是C++ 、C的标准中所定义的,其意图是为了提供给操作系统一个返回值来表现程序的执行状态。
- 如 return -1、 在CentOs中使用 echo $?查看,返回值是 255
- 附赠 Linux标准错误表2
- 在大多数系统中,main 函数的返回值是一个状态指示器。
- 怎么理解这句话?
- 结合上面的错误码表理解,这个返回值,就是应对的对应错误类型定义。 0 00代表正常。
- 什么系统里不是?如果要移植怎么处理?
- 支持void main(){...}的操作系统,并且这里的void 并不是在内层中缺省为0。
- 如果要移植需要将 将 无符号类型返回值,改为int 类型并且添加返回条件,如果是自研操作系统,最好可以加上完整的宏定义 。
- 每一种操作系统都有自己的方式告诉用户 main 函数返回什么内容。
详细的示例可以说说吗?
参考2
- GNU、微软编译器、MinGW这三者之间的 区别怎样?
- mingw(Minimalistic GNU for Windows)编译器系统,建立在GCC和binutils项目上。MinGW提供了一套简单方便的Windows下的基于GCC程序开发环境,是一套GNU工具集合(一系列免费的Windows使用的头文件和库文件,同时整合了GNU工具集,特别是GNU程序开发工具,如经典gcc,g++,make等)。该集合允许人们在没有第三方动态链接库的情况下使用GCC产生Windows32程序。它在windows平台模拟了Linux下的GCC开发环境,为C++的跨平台提供了良好的基支持。
- GNU不是一个公司名,而是一个软件项目名,它开发了许多应用程序。
- GCC全称是GNU C Compiler ,最早的时候就是一个C编译器。但是后来因为这个项目里边集成了更多其他不同语言的编译器,GCC就代表 the GNU Compiler Collection,所以表示一堆编译器的合集。
- G++则是GCC的c++编译器
- 微软编译器是微软自己的编译方式,使用方式是cl -GX progl.cpp ![[Pasted image 20220822210401.png]]
- ![[Pasted image 20220822164134.png]]
- 当在命令行输入 ./a.out并执行的时候,它在底层做了什么样的操作步骤?
- 这里是可以联系上面的main 部分联合解释的,操作系统调用C++ runtime system ,C++ runtime system 调用main ,然后进入程序内部执行逻辑。
- 从操作系统角度就是,从内存到处理器,经历了中级调度和低级调度。
- 为什么说执行程序后,必须发出一个适当的echo命令?他是为了干什么?不发后果会怎样?![[Pasted image 20220822210939.png]]
- 这个是操作系统级的处理逻辑,是为了得知程序的运行结果。
- 如果没有这个东西,对于操作系统来说,他将不能够监听程序的运行状态,也就没有办法完成对程序的监管。
- 使用return -1这样故意搞怪,怎么查看返回值?
参照上文,类Linux系统下使用 echo $?
由输入输出引发的 库发散。
- #include 这句话,所引用的iostream 这个库是什么?
- 他是C++提供的输入输出标准库。分为istream 和 ostream两部分,
- iostream 和 using namespace std;是不是只用一个就可以了?如果不是,那么他们的区分在哪里?
- 对于这些c++ 标准库,而言,使用 using namespace std; 是可以包括的。
- 但是对于那些开源三方,并不可以。
- 另外,这些标准库和命名空间的重复效果是为了避免大量的头文件使用过程中的命名重复问题。
- 在这种情况下,编译器只能先声明先使用,有时不能正确表达,所以引入统一命名的全局空间std。
- C++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h,即出现了现在的头文件。当使用的时候,该头文件没有定义全局命名空间,必须使用C++所规定的标准的命名空间(即:namespace std),这样才能正确使用cout、endl等功能。
3.被忽视的流 —— 流对象产生消费对象,流本身是什么?
- 产生于输入端,消费于输出端,
- 流本身是字符序列。而字符序列和字符串队列是不一样的,这里只说前者—— 他是 0101这样的二进制字符,或者64位机上的16进制存储空间的寄存器字符,的一个抽象唯一性元素集合,
- 是一个类似元素周期表的表格,而不是由元素构成的化合物集群。
- 重定向是怎么回事?
- 重定向是说我们将 默认的:系统将这些对象与执行程序的窗口联系起来。变更成为:将这些对象与所选择的文件联系起来。
- cin 和scanf之间的差距仅是语言的差异吗?
- 不是这样的。
- cin 不单是一个函数,它更是一个对象,是对于IO输入的功能需求的一个抽象封装。
- scanf 是一个c语言的函数,不具备更多的扩展操作方式。比如继承这样的方式。
- #include 这被称之为预处理指示:那么什么是预处理指示?预处理发生在哪个阶段?预处理之后做什么?预处理是谁来处理的? 是为谁准备的?如果不做会怎样?
- 表达式 由什么构成?
- 操作数和操作符
- 操作数是变量或者其他对象类型。
- 操作符是运算操作符。
- 每一个表达式都会产生一个结果
- 操纵符 endl它特殊在哪里? 将其称之为一个特殊值,那这个值是多少?使其变得特殊的原因在哪里?
- 一条记录数据从程序中到显示出来,这个过程中经历了几个部分?
由IOstream库写入到缓冲区,
刷新缓冲区,立刻显示到标准输出上。
为什么刷新缓冲区,可以让用户立刻看到写入内容?
- ![[Pasted image 20220823172347.png]]这是为什么?
- std::cout 的写法使用了作用域操作符 ( scope operator , ::操作符)
- iostream库定义了接受全部内置类型的输入输出操作符版本
- ![[Pasted image 20220823174632.png]]这里可以配代码说明展示么?为什么空格符不能出现在预处理指示中?
- ![[Pasted image 20220823174857.png]] 那么初始化时侯,定义初始化和先定义再初始化,两者之间有什么隐式问题?
- 如果采用C99 编译c 代码时候,for循环不支持 使用 int i= 0;来初始化局部变量,需要先在外部进行声明,再在这里使用。
- #c++primer #习题
1.3:
#include using namespace std; int main() { cout << "Hello,World"<< endl; return 0; }
1.4:
#include using namespace std; int mult(int i, int k) { return i*k; } int main() { int i = 3; int k = 4; mult(i,k); return 0; }
#include using namespace std; int main() { cout << "hello" ; cout << " " ; cout << "world" ; cout << 10 < }
1.6:![[Pasted image 20220823191150.png]]
首先,不合法。
第一,这是单条复合表达式,不能在中间的各行尾部加; 分号表示当前语句结束,会导致后面的 <<输出操作符找不到左值不能构成一个完整的表达式。
第二,除去分号之后,剩余的部分依旧有回车符\n或者\r\n这取决于程序编码器的字符编码方式,或者系统的保存方式,也就是说,再有的编译器下可能会造成不能正确识别的情况。
服务器高级架构体系:https://ke.qq.com/course/417774?flowToken=1010783
- ![[c++中为什么需要main函数的解释如下:]] ↩︎
- ![[Linux——标准错误码表]] ↩︎ ↩︎