C进阶:预处理(上)

简介: C进阶:预处理

一.代码运行是的两种环境

1.翻译环境,在这个环境中源代码被转换为可执行的机器指令。

2.执行环境,它用于实际执行代码

下面主要讲解翻译环境。

二.翻译环境

从.c 文件到 .exe 文件需要经过编译器的翻译,而翻译又分为 编译和链接两个部分

编译又分为三个部分:

1.预编译:又叫预处理,在这个部分主要完成头文件的包含,#define的替换,注释的删除;

2.编译:主要完成语法分析,词法分析,词义分析,符号汇总(符号包括全局性的变量和函数),生成汇编代码;

3.汇编:生成二进制指令,形成符号表(符号表是由符号和其地址组成的);

链接:合并段表,合并符号表(在这个阶段会发现未定义的函数)

见下图:

三.预定义符号

__FILE__    //进行编译的源文件

__LINE__   //文件当前的行号

__DATE__   //文件被编译的日期

__TIME__   //文件被编译的时间

__STDC__   //如果编译器遵循ANSI C,其值为1,否则未定义

四.#define

1.define  定义宏

宏的申明方式:

#define name( parament-list ) stuff

其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。

注意 name 需与后面的括号紧密相连,不可以有空格,如果有任何空白存在,参数列表就会被解释为stuff的一部分。

注意当我们定义宏的时候,不要吝啬括号!

来看下面一个例子:

1. #define MOD(x,y) x*y
2. 
3. int main()
4. {
5.  int m = MOD(2+3,2);
6.  printf("%d\n", m);
7.  return 0;
8. }

对初学者来说,这段代码的答案很容易被认为式10,但事实并非如此,因为宏是在预处理阶段先替换掉,然后在进行计算,所以在没有括号的情况下,替换后是这样的:2+3*2=8;所以若是想要得到10这个结果,就要加上括号,即:

#define MOD(x,y) ((x)*(y))

2.带有副作用的宏参数

我们知像是前置++ ,后置++这种的运算符是会改变操作数的值属性的,那它如果应用到#define 定义的宏中会是怎么样呢?

我们来看下面这个例子:

1. #define MAX(x,y) ((x)>(y)?(x):(y))
2. 
3. int main()
4. {
5.  int a = 4;
6.  int b = 6;
7.  int m = MAX(a++, b++);
8.  printf("m=%d\n", m);
9.  printf("a=%d b=%d\n", a, b);
10.   return 0;
11. }

最后的答案会是多少呢?

首先完成宏参数的替换:((a++)>(b++)?(a++):(b++))

后置++是先使用后++,因为4<6,所以执行后面的 b++,经过前面的++,此时a=5,b=7,所以先把7赋给m,然后b++,得到b=8;

m=7  a=5  b=8

总结:

1.#define 定义的符号需要先原封不动的替换掉,所以建议在#define 后面不加 ' ; ' ;

2.#define 定义的宏不要吝啬括号,以免出现出乎意料的结果;

3.避免使用带有副作用的运算符。

五.#define定义宏 与函数对比

六.预处理指令

所有的预处理指令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理指令应从第一列开始。下面列出了所有重要的预处理指令:

目录
相关文章
|
5天前
|
编译器 C++
C++语言预处理器学习应用案例
【4月更文挑战第8天】C++预处理器包括条件编译、宏定义和文件包含等功能。例如,条件编译用于根据平台选择不同代码实现,宏定义可简化常量和变量名,文件包含则用于整合多个源文件。示例中展示了如何使用`#ifdef`等指令进行条件编译,当`DEBUG`宏定义时,`PRINT_LOG`会打印调试信息,否则不执行。
17 1
|
5天前
|
C语言
【C语言进阶篇】你真的了解预处理吗? 预处理详细解析
【C语言进阶篇】你真的了解预处理吗? 预处理详细解析
38 0
|
10月前
|
编译器 C++
C进阶:预处理(下)
C进阶:预处理(下)
52 0
|
9月前
预处理的学习
预处理的学习
35 0
|
12月前
|
编译器 Linux C++
【C进阶】——预处理详解(二)
【C进阶】——预处理详解(二)
102 0
|
12月前
|
Linux C语言 C++
【C进阶】——预处理详解(一)
【C进阶】——预处理详解(一)
47 0
|
11月前
|
编译器 C语言 C++
C语言编程—预处理器
预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Preprocessor)简写为 CPP。
65 0
|
12月前
|
编译器 C语言 C++
万字【C语言程序的预处理】各种知识点的讲解2
万字【C语言程序的预处理】各种知识点的讲解
|
编译器 C++
c++入门篇之C++ 预处理器
预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。
|
编译器
【学习笔记之我要C】预处理
【学习笔记之我要C】预处理
60 0