【无标题】

关于面试的问题_1

注: 来自AI 和自己的搜索

gcc 编译的完整流程

主要是链接阶段动态库的作用

1. 预处理(Preprocessing)

预处理阶段由预处理器(如cpp)负责,将源代码中的预处理指令进行处理。

  • 宏替换:展开代码中的宏定义,如#define定义的符号会被实际的值或表达式替换。
    • 例如,#define PI 3.14,在代码中PI会被替换为3.14
  • 头文件包含:将头文件中的内容插入到包含指令#include的地方。
    • 例如,#include <stdio.h>会将stdio.h文件的内容插入到该指令处。
  • 条件编译:根据条件编译指令(如#ifdef#ifndef#if等)的条件,决定是否包含特定的代码块。
    • 例如,#ifdef DEBUG只有在定义了DEBUG宏的情况下,才会包含其中的代码。
  • 注释删除:去除代码中的注释。
    • 例如,/* this is a comment */// this is a comment 都会被删除。

工具和命令

gcc -E source.c -o source.i

该命令将预处理后的代码保存为source.i文件,这个文件是纯C语言代码,已经展开了宏、包含了头文件,并删除了注释。

2. 编译(Compilation)

编译阶段由编译器前端(如cc1)负责,将预处理后的代码转换为汇编代码。这个阶段主要包括以下步骤:

  • 词法分析:扫描预处理后的代码,将代码分割成一个个称为“记号”(Token)的基本元素,如关键字、标识符、操作符等。
    • 例如,将int a = 5;分解为inta=5;等记号。
  • 语法分析:将词法分析生成的记号流组织成语法树(AST),以理解代码的结构。
    • 例如,int a = 5;被解析为变量声明语句,其中aint类型,并初始化为5
  • 语义分析:检查语法树的语义,确保代码符合语言的语义规则,如类型检查、作用域检查等。
    • 例如,确保a的类型是int,而不是float或其他不兼容的类型。
  • 中间代码生成:将语法树转化为一种中间表示形式,通常是独立于机器的三地址代码或其他中间表示(IR)。
    • 例如,将a = b + c;表示为t1 = b + c; a = t1;
  • 优化:对中间代码进行各种优化,提升运行效率和减少代码大小。
    • 例如,删除冗余代码、进行循环优化、寄存器分配等。
  • 汇编代码生成:将优化后的中间代码转换为目标机器的汇编代码。
    • 例如,将a = b + c;生成对应的汇编指令。

工具和命令

gcc -S source.i -o source.s

该命令生成汇编代码文件source.s

3. 汇编(Assembly)

汇编阶段由汇编器(如as)负责,将汇编代码转换为二进制的目标文件(即机器码)。

  • 符号表生成:在汇编过程中,汇编器生成一个符号表,用于存储变量名、函数名与它们在内存中位置的对应关系。
  • 机器码生成:汇编器将每条汇编指令转换为目标机器的二进制指令。
    • 例如,将movl $5, %eax转换为相应的二进制代码。
  • 生成目标文件:最终生成的目标文件(.o文件)包含了机器码和符号表,但还未解决外部符号(即不同模块之间的符号引用)。

工具和命令

gcc -c source.s -o source.o

该命令生成目标文件source.o

4. 链接(Linking)

链接阶段由链接器(如ld)负责,将多个目标文件和库文件链接成最终的可执行文件。这个阶段包括以下步骤:

  • 符号解析:链接器解析各目标文件和库文件中的符号,解决外部符号的引用问题。
    • 例如,在一个文件中调用另一个文件中定义的函数,链接器需要将调用与定义关联起来。
  • 地址绑定:为每个符号(变量、函数等)分配实际内存地址。
    • 例如,将main函数绑定到可执行文件中的特定内存地址。
  • 生成可执行文件:链接器生成最终的可执行文件,该文件包含了所有目标文件和库文件的机器码,以及最终的符号表和地址信息。

工具和命令

gcc source.o -o executable

该命令生成可执行文件executable

5. 动态链接与加载(运行时)

除了静态链接生成的可执行文件外,还有动态链接和加载过程,这发生在程序运行时。

  • 动态链接:在程序运行时,动态链接器(如ld-linux.so)将程序依赖的共享库动态加载到内存,并解析动态符号。
  • 加载程序:操作系统加载器将可执行文件加载到内存中,并开始执行,从入口点(通常是main函数)开始运行程序。

总结

整个GCC编译过程可以总结为:

  1. 预处理:展开宏、包含头文件、删除注释,生成预处理后的代码。
  2. 编译:经过词法分析、语法分析、语义分析和优化,生成汇编代码。
  3. 汇编:将汇编代码转换为目标文件(机器码)。
  4. 链接:将多个目标文件和库文件链接成最终的可执行文件。
  5. 动态链接与加载(运行时):在程序执行时,动态链接库被加载,并解析动态符号,最终执行程序。

这个详细的流程展示了从源代码到最终可执行程序的每个细节步骤。每个阶段都有其特定的任务和工具,确保程序能够正确、高效地被执行。

const 修饰变量前后的内存变化

这个被问我是真不知道
c语言中const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放。

而const局部变量(局部变量就是在函数中定义的一个const变量,)存储在栈中,代码块结束时释放。

在c语言中可以通过指针对const局部变量进行修改,而不可以对const全局变量进行修改。因为const全局变量是存储在只读数据段

而c++中,一个const不是必需创建内存空间,而在c中,一个const总是需要一块内存空间。

在c++中是否要为const全局变量分配内存空间,取决于这个const变量的用途,如果是充当着一个值替换(即就是将一个变量名替换为一个值),那么就不分配内存空间,不过当对这个const全局变量取地址或者使用extern时,会分配内存,存储在只读数据段。也是不能修改的。

c++中对于局部的const变量要区别对待:

对于基础数据类型,也就是const int a = 10这种,编译器会把它放到符号表中,不分配内存,当对其取地址时,会分配内存
对于基础数据类型,如果用一个变量初始化const变量,如果const int a = b,那么也是会给a分配内存
对于自定数据类型,比如类对象,那么也会分配内存。

c中const默认为外部连接,c++中const默认为内部连接.当c语言两个文件中都有const int a的时候,编译器会报重定义的错误。而在c++中,则不会,因为c++中的const默认是内部连接的。如果想让c++中的const具有外部连接,必须显示声明为: extern const int a = 10。
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/woainilixuhao/article/details/86521357

类和对象在编译时如何被处理

盲区,完全就是盲区

单片机的内存管理

https://blog.csdn.net/weixin_42550185/article/details/131156144?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172370982916800182791064%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=172370982916800182791064&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-131156144-null-null.142v100pc_search_result_base6&utm_term=%E5%8D%95%E7%89%87%E6%9C%BA%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86&spm=1018.2226.3001.4187

uart 通信协议

https://blog.csdn.net/wuyiyu_/article/details/137342569?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_utm_term~default-0-137342569-blog-132943014.235v43pc_blog_bottom_relevance_base5&spm=1001.2101.3001.4242.1&utm_relevant_index=3

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值