C语言: 预处理
1. 字符映射
键盘有多种标准规格,例如常用的IBM 104键盘标准,然而不是所有键盘都能打出像#这样的符号,因此C语言的预处理引入了字符映射机制。如果程序员要求,预处理会按照约定对源代码中的字符进行映射处理,例如将一些扩展的三元字符转换为源代码字符(??=转换为#,??/转换为\等等)。字符映射是预处理的第一步。
2. 物理行的合并
预处理器在连续读到反斜线符和换行符时会将这两个字符删除,从而将当前所在的物理行和下一个物理行合并为一个逻辑行,例如
printf("That's wond\
erful!\n");
等价于
printf("That's wonderful!\n");
在定义一些比较复杂的宏或字符串时使用这个方法可以方便换行阅读。物理行合并是预处理的第二步。
3. 注释的替换
在第三步,预处理器将注释替换为一个空格字符。
4. 预处理指令
预处理器会将所有以#开头,以换行符结束的字符串作为一条预处理指令,但这个规则不受反斜线符和换行符组合的影响,因此预处理指令可以用多个物理行表示。
4.1 #define-basic
#define指令可以实现字符串替换,其前后分为三个部分,分别是#define、宏、替换列表。宏可以分为类对象宏或类函数宏,宏的命名方式和变量标识符一样,可以由字母、数字、下划线组成但首字符不能是数字。如果宏中出现了圆括号,那么将作为类函数宏处理,否则认为是类对象宏。例如
#define PX printf("X is %d.\n",x)
#define PR(Z) printf("The result is %d.\n", Z)
int main() {
int x=0;
PX;
PR(x);
return 0;
}
预处理后的结果为
int main() {
int x=0;
printf("x is %d",x);
printf("The result is %d.\n",x);
return 0;
}
宏可以被重定义,代码在前面使用#define定义了一个宏MACRO之后,可以在后面再使用#define更改MACRO的定义。
4.2 #define-##、#、...、__VA_ARGS__
##可以实现类函数宏中标识符的粘合。例如定义#define INT(name) x##name,则INT(1)将转换为x1。之所以这样做是因为#define的文本替换是以标识符为单位的,如果直接定义#define INT(name) xname,由于xname与name不是同一个标识符,INT(1)将不能转换为x1。
#可以实现标识符的字符串化,这个功能配合字符串的连接特性可以解决对字符串进行文本替换的问题。之所以这样做是因为#define不对字符串的内容进行文本替换。例如#define PSQR(X) printf("The square of X is %d.\n",((X)*(X)));则替换列表中的第一个X将不会被替换。解决的办法是写为#define PSQRprintf("The square of " "#X" " is %d.\n",((X)*(X)));,这里借助了字符串的可连接性。
...和__VA_ARGS__可以实现可变参数宏,例如定义#define PR(...) printf(__VA_ARGS__),则使用PR即可代替printf函数。注意...只能作为最后一个参数,#define FPR(X,...,Y) fprintf(X,__VA_ARGS__,Y)是错误的。
C语言: 预处理的更多相关文章
- 面试问题4:C语言预处理包括哪些
问题描述:C语言 预处理包括哪些操作 C语言的三种预处理包括:宏定义(#define).文件包含(#include).条件编译(#if.#else.#endif). 对于宏定义的介绍: 宏定义必须写在 ...
- 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出
[源码下载] 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 预处理命令 输入 ...
- C语言预处理运算符
转自C语言预处理运算符 预处理还需要运算符?有没有搞错? ^_^, 没有搞错,预处理是有运算符,而且还不止一个: #(单井号) -- 字符串化运算符. ##(双井号 )-- 连接运算符 #@ ...
- C语言预处理指令的初步了解
所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理是C语言的一个重要功能,它由预处理程序负责完成.当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分 ...
- C 语言入门第八章--C语言预处理命令
例如:#include ,这种以#号开头的命令称为预处理命令. ===C语言宏定义(#define的用法)==== #define 叫做宏定义命令,它也是C语言预处理命令的一种.所谓宏定义,就是用一个 ...
- C语言预处理理论2
C语言预处理理论1.头文件包含(1)#include <>和#include ""区别:<>专门用来包含系统提供的头文件(就是系统自带的,不是程序员自己写的 ...
- C语言预处理理论
C语言预处理理论1.从源码到可执行文件的过程(1)源码.c->(编译)->elf可执行程序(2)源码.c->(编译)->目标文件.o->(链接)->elf可执行程序 ...
- C语言预处理编译链接各个阶段错误,分阶段的说一下
C语言预处理编译链接各个阶段错误,分阶段的说一下 C语言预处理编译链接各个阶段错误,分阶段的说一下比如指针异常,数组下标越界什么的 我来答 1个回答 #热议# 你觉得这辈子有希望看到996消失 ...
- C语言 预处理三(条件编译--#if)
//#if 条件编译 //一般用于产品各个版本的语言包 #include<stdio.h> #include<stdlib.h> //#都是预处理指令,条件表达式必须在预处理里 ...
- C语言 预处理二(宏定义--#define)
//#define 宏定义(宏定义一般大写) //知识点一-->#define的作用域:从#define开始,从上往下,如果遇到#undef就到#undef处结束,如果没有就是作用于当前整个文件 ...
随机推荐
- 免安裝、免設定的 Hadoop 開發環境 - cloudera 的 QuickStart VM
cloudera 的 QuickStart VM,為一種免安裝.免設定 Linux 及 Hadoop,已幫你建好 CDH 5.x.Hadoop.Eclipse 的一個虛擬機環境.下載後解壓縮,可直接以 ...
- Thread.Sleep引发ThreadAbortException异常
短信平台记录日志模块,是通过异步方式来记录的,即日志工具类里初始化一个Queue对象,公共的写日志方法的处理逻辑是把日志消息放到Queue里.构造器里设定一个死循环,不停的读队,然后把日志消息持久化到 ...
- VMWare vSphere Client 克隆虚拟机 更改IP
克隆虚拟机后,查看该虚拟机所分配的MAC地址. 打开控制台,进入linux界面. 打开/etc/udev/rules.d/70-persistent-net.rules内容如下面例子所示: # vi ...
- java compiler level does not match the version of the installed java project facet 解决方案
项目出现 java compiler level does not match the version of the installed java project facet 错误,一般是项目移植出现 ...
- python基础篇----字符串unicode
python中处理中文常要用到unicode,因为较容易遇到字符串编码的问题,我一般都是将字符串统一转成unicode去处理 python中定义一个unicode字符串,可以在字符串前面加u: str ...
- VS-默认端口导致项目不能加载的解决方案
- es6新特性分享
1.字符串查找es5使用是indexOf() 返回字符第一次出现的位置int值es6新增了3个方法:includes()/startsWith()/endWith()返回bool值includes = ...
- 【HBase】HBase Getting Started(HBase 入门指南)
入门指南 1. 简介 Quickstart 会让你启动和运行一个单节点单机HBase. 2. 快速启动 – 单点HBase 这部分描述单节点单机HBase的配置.一个单例拥有所有的HBase守护线程- ...
- 总结JavaScript事件机制
JavaScript事件模型 在各种浏览器中存在三种事件模型: 原始事件模型 , DOM2事件模型 , IE事件模型. 其中原始的事件模型被所有浏览器所支持,而DOM2中所定义的事件模型目前被除了IE ...
- JS详细教程(下)
五.数组 数组是数据的有序列表,每个元素在数组中都有数字位置编号,也就是索引.JS中的数组是弱类型,每一项都可以保存任何类型的数据. 创建数组 ①使用Array构造函数 var arr=new Arr ...