首先简单介绍一下编译的过程~
1.编译:把.c变成一个exe文件
2.运行:把exe跑起来,执行里面的逻辑.
此处的"编译"是一个"广义"的编译,这个编译其实还可以再拆成很多个步骤.
(1)预处理:
编译器先对源代码进行一个初步的处理,会执行代码中的预处理指令,输入内容是.c文件,输出结果还是一个.c文件,在c语言中,以#开头的,都是预处理命令.
(2)编译(狭义的编译):
把c语言文件变成汇编语言的文件
(3).汇编:
把汇编语言的文件转换成二进制的机器指令.
(4).链接:
每个.c文件都会生成对应的机器指令文件,链接的过程就是把这若干个.c文件生成的结果合并起来
__FILE__ __LINE__最常用的场景就是在日志中打印
printf打印一个具体的日志时,加上__FILE__和__LINE__,就可以区分出当前打印函数的位置.
__DATE__和__TIME__表示编译时候的日期和时间.(和运行是没有关系)
__STDC__表示是否遵守c语言标准.如果遵守,结果就是1,不遵守,结果可能是0或者未定义.
通过#define可以做到很多事情~
1.定义常量
2.给类型定义别名
3.自定义一些"关键字"
4.通过宏作为一些"编译开关"
5.定义一个代码片段(让宏看起来像一个函数一样)
所谓的宏,本质上就是一个"文本替换"
宏的优势:
1.参数可以是任意类型,写一个代码就可以针对多个情况来使用.
2.避免了函数调用传参的开销,这个操作的速度就要比函数调用更高效.
宏的劣势:
1.宏展开后容易出现不预期的效果
2.使用宏,非常不方便调试,尤其宏比较复杂的时候,也不方便阅读.
3.宏无法递归
4.宏没有参数检查
宏建议一般能不用就不用.
条件编译也是一种预处理指令,例如#if,#else,#endif,#ifdef,#ifndef.
就是满足条件,编译一部分代码,不满足条件,在编译另一部分代码
典型应用一:一份代码,同时兼容开发环境和发布环境~
在开发的时候可能会有很多"调试代码",如果在发布的时候一行一行删掉,风险太大,可能会漏删,也可能会误删.
典型应用二:一份代码兼容不同的系统~
写代码考虑到跨"平台",一份代码要支持不同的操作系统
典型应用三:防止头文件被重复包含~
#pragma once