网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
2️⃣ 宏替换
3️⃣ 去注释
test.c -> test.i
编译:
1️⃣ 把C语言代码转化为汇编代码
2️⃣ 进行了 语法分析,词法分析,语义分析,符号汇总(全局符号例如main函数、函数名)
test.i -> test.s
汇编:
1️⃣把汇编代码转换成二进制指令
2️⃣ 形成符号表(函数名加上地址)
test.s -> test.o
链接:
1️⃣ 合并段表(把相同的内容合并到一个区域)
2️⃣ 符号表的合并和重定位(声明处的地址没有意义,合并选择有意义的)
test.o -> text.exe
1.3 运行环境
程序执行的过程:
1)程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2)程序的执行便开始。接着便调用main函数。
3)开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4)终止程序。正常终止main函数;也有可能是意外终止。
二、详解预处理
2.1 预定义符号
C语言提供了一些能直接被使用的符号:
\_\_FILE\_\_ //进行编译的源文件
\_\_LINE\_\_ //文件当前的行号
\_\_DATE\_\_ //文件被编译的日期
\_\_TIME\_\_ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
int main()
{
FILE\* pf = fopen("test.txt", "w");
if (pf == NULL)
{
return EXIT_FAILURE;
}
for (int i = 0; i < 5; i++)
{
fprintf(pf, "file:%s line:%d date:%s time:%s\n", \_\_FILE\_\_, \_\_LINE\_\_, \_\_DATE\_\_, \_\_TIME\_\_);
}
fclose(pf);
pf = NULL;
return 0;
}
2.2 #define
语法:
#define name stuff
#define MAX 100
#define STR "abc"
int main()
{
printf("%d %s", MAX, STR);
return 0;
}
预处理后:
int main()
{
printf("%d %s", 100, "abc");
return 0;
}
#define的后面不要加 ;
续航符:
#define DEBUG\_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
\_\_FILE\_\_,\_\_LINE\_\_ , \
\_\_DATE\_\_,\_\_TIME\_\_ )
2.3.1 #define定义宏
#define name( parament-list ) stuff
比如现在实现一个平方的宏:
#define SQUARE( x ) ((x) \* (x))
int main()
{
printf("%d", SQUARE(5));
return 0;
}
因为宏是直接替换代码,所以有些情况下会有符号优先级问题,所以应该尽量多加一些括号。
2.3.2 #define 替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先
被替换。- 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
- 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
述处理过程。
注意:
- 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
- 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
2.3.3 #和##
#:
把参数写进字符串
#define PRINT(n) printf("the value of " #n " is %d\n", n)
int main()
{
int n = 10;
PRINT(n);
return 0;
}
#n会转化成"n"。
##:
合并符号
#define CAT(a, b) a##b
int main()
{
printf("%s\n", CAT("abc", "def"));
int ABC = 1;
printf("%d\n", CAT(A, BC));
return 0;
}
2.3.4 带副作用的宏
#define MAX(a, b) (a) > (b) ? (a) : (b)
int main()
{
int a = 5;
int b = 4;
int m = MAX(a++, b++);
printf("%d\n", m);
printf("%d %d", a, b);
return 0;
}
结果:
6
7 5
本意是求较大值,这种重复计算就是副作用。
2.3.5 宏和函数
比较大小的宏和函数:
#define MAX(a, b) a > b ? a : b
int Max(int a, int b)
{
return (a > b ? a : b);
}
宏的优点:
1️⃣ 函数必须声明类型,而宏不用,宏是类型无关的。
2️⃣ 宏的效率要高于函数,因为函数需要创建栈帧和参数传参等。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
必须声明类型,而宏不用,宏是类型无关的。
2️⃣ 宏的效率要高于函数,因为函数需要创建栈帧和参数传参等。
[外链图片转存中…(img-w8WYsxBR-1715533906489)]
[外链图片转存中…(img-F56xC31g-1715533906489)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新