嵌入式C语言学习笔记-编译过程与常见错误处理

Gcc概述:把高级语言转化为机器语言的工具集

gcc -v   //查询gcc版本
​
gcc -o 输出文件名 输入文件名(源文件) //编译
./输出文件名
​
gcc -v -o build text.c  //详细显示gcc编译时的过程

C语言编译过程介绍

1.预处理阶段,GCC编译器执行宏替换、头文件包含、条件编译等操作。这个阶段的目的是处理源代码中的预处理指令,生成一个经过预处理的源代码文件,通常以.i为文件扩展名。预处理后的代码包含了所有必要的头文件内容和宏定义的展开结果,但不包含任何编译指令或语法分析信息(不对代码进行检查)。

2.编译阶段是将预处理后的源代码转换为汇编语言代码的过程。在这个阶段,编译器进行词法分析、语法分析、语义分析和优化。编译器检查代码的语法错误,分析变量和函数的使用情况,并执行代码优化以提高程序的运行效率和减少内存占用。生成的汇编语言代码对应于目标平台的机器指令集,但仍以人类可读的形式存在

3.汇编阶段是将汇编语言代码转换为机器语言的二进制代码的过程。汇编器处理汇编语言指令,将它们转换为机器代码,并生成目标文件,通常具有.o或.obj的文件扩展名。这个阶段涉及符号解析和重定位等操作,确保生成的机器代码可以在目标硬件上正确执行。

4.链接阶段是将一个或多个目标文件与其依赖的库合并生成最终的可执行文件。链接器处理符号解析、地址和偏移量分配等任务,确保所有外部引用都被正确解决。在这个阶段,动态链接库(DLLs)或静态链接库(static libs)中的函数和数据被整合到最终的可执行文件中。链接完成后,生成的文件可以在操作系统上运行,不需要额外的库文件。

【问题】 define include 是关键字吗? 不是,define include在预处理阶段就已经处理完

预处理 c文件 -> .i文件  命令:gcc -E -o a.i text.c
编译  c文件 -> .s文件   命令:gcc -S -o a.s text.c(gcc的编译过程会包括预处理)
汇编  .s文件 -> .o文件  命令:gcc -c -o a.o a.s
链接                   命令:gcc -o

C语言编译常见错误举例
预处理错误
【问题】
 not found:头文件包含出错,如自定义的头文件和需要编译的文件不在同一目录下
【解决方法】
1.#include "abc.h" -> #include "./inc/abc.h"
2.增加选项:gcc -I查找头文件的目录   gcc -I./inc -o build text.c

编译错误
【问题】
;  {}  缺少

链接错误
【问题】
collect2:链接器报错
​
原材料少了:undefined reference to 'name'
​
原材料多了:multiple definition of 'name',多次实现了标签,只保留一个
​

预处理的使用
#include 
包含头文件 
在当前的位置上,对这个文件内容进行展开,再通过gcc把这个文件进行编译
​
#define
宏  ->  替换
不进行语法检查的展开
#define 宏名 宏体          ->安全->加括号
#define ABC (5+3)
​
宏函数
#define ABC(x) (5+(x))   ->5+x对x进行替换
​
​
#ifdef #else #endif 条件预处理
​
在程序开发的过程中,通常会有两个版本
调试版本debug
发行版本release
需求:在调试时输出某些调试的信息,但在发行版本时将这些调试信息关闭
​
int main()
{
#ifdef ABC
    printf("------------");//调试信息,发行版本中不需要打印
#endif
    printf("hello world!");//普通输出信息
    return 0;
}
​
当程序预先已经定义了ABC时,#ifdef ABC 这句话为真,将执行调试信息的打印输出并输出hello world!
反之,则不打印输出调试信息,只输出hello world!
​
利用-D选项在输入编译命令时,提前定义ABC,而不用修改源代码
gcc -DABC 等价于在源文件添加  #define ABC
​
命令:gcc -DABC -o build text.c
​
​
预定义宏  系统定义的宏 前后都是两个下划线
__FUNCTION__  函数名
__LINE__      行号
__FILE__      文件
​
在调试开发的过程中,利用预定义宏,可以迅速找到报错语句的位置
printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);

宏展开下的# , ##
在宏体中实现
#  字符串化
#define ABC(x) #x
​
## 连接字符
#define ABC(x) day##x  ->dayx
​
代码:
#include <stdio.h>
#define ABC(x)  #x
#define DAY(x)  myday##x
int main()
{
    int myday1=10;
    int myday2=20;
    
    printf("ABC(ab\n)");
    printf("the day is %d and %d\n",DAY(1),DAY(2));
    return 0;
}
程序输出:
"ab"
"the day is 10 and 20"
​

​

欢迎批评指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值