【C/C++】C预处理器

C预处理器处理程序的源代码,在编译器之前运行,通常以"#"开头。

C语言的预处理主要有三个言而的内容:

1) 宏定义和宏替换;

2) 文件包含;

3) 条件编译。

1. 宏定义和宏替换

"宏"是借用汇编语言中的概念,为的是在C语言程序中方便的作一些定义和扩展。这些语句以#define开头,分为两种:符号常量的宏定义和带参数的宏定义。

1) 符号常量的宏定义和宏替换

1 #define 标识符 字符串

其中标识符就称为宏名称,注意宏定义末尾不加分号。

由于预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,故预处理是不做语法检查的。且宏定义不分配内存,变量定义才会分配内存。

2) 带参数的宏定义和宏替换

1 #define 标识符(参数列表) 字符串

对带有参数的宏定义进行替换时,不仅对宏标识符作字符串替换,还必须作参数的替换。

为了避免宏替换时发生错误,宏定义中宏参数应加上括号。

【示例】有如下一段代码:(2011腾讯)

1 #define ADD(x, y) x+y
2 int m = 3;
3 m += m*ADD(m, m); 

则m的值为( )

A. 15        B. 12        C. 18        D. 58

【解答】A。 m+=m*ADD(m,m)将会被替换为m+=m*m+m,故m=15。

宏替换的本质很简单——文本替换。关于宏定义与宏替换请注意以下几点:

1) 宏名一般用大写,宏名和参数的括号间不能有空格,宏定义末尾不加分号;

2) 宏替换只作替换,不做语法检查,不做计算,不做表达式求解;

3) 宏替换在编译前进行,不分配内存,函数调用在编译后程序运行时进行,并且分配内存;

4) 函数只有一个返回值,利用宏则可以设法得到多个值;

5) 宏替换使源程序变长,函数调用不会;

6) 宏替换不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。

  注意:应尽量少使用宏替换。在C++中,宏替换实现的符号常量功能由const、enum代替,带参数的宏可由模版内联函数代替。

2. 文件包含

#include 接受以下两种形式:

1) #include <standard_header>

2) #include "my_file.h"

如果头文件名括在尖括号(<>)里,那么认为该头文件是标准头文件。编译器会在预定义的位置集合中查找头文件,这些预定义的位置可以通过设置查找路径环境变量或者通过命令行选项来修改。使用的查找方法因编译器的不同而差别迥异。如果头文件在一对引号里,那么认为它是非系统头文件,非系统头文件的查找通常开始于源文件所在的路径。

3. 条件编译

提供条件编译措施使同一源程序可以根据不同编译条件(参数)产生不同的目标代码,其作用在于便于调试和移植。

条件编译控制语句有不同形式:

1 #if/ifdef/ifndef
2 #elif
3 #else
4 #endif

文件包含需要考虑避免多重包含的问题,下面介绍如何利用条件编译语句避免多重包含。

在编写头文件之前,我们需要引入一些额外的预处理设施。预处理器允许我们自定义变量。预处理器变量的名字在程序中必须是唯一的。任何与预处理器变量相匹配的名字的使用都关联到该预处理器变量。

为了避免名字冲突,预处理骂人变量经常用全大写字母表示。

预处理器有两种状态:已定义或未定义。#define指示接受一个名字并定义该名字为预处理器变量。#ifndef检测指定的预处理器变量是否未定义。如果预处理变量未定义,那么跟在其后的所有语句都被处理,直到出现#endif。

可以使用这些设施来预防多次包含同一头文件:

1 #ifndef SALESITEM_H
2 #define SALESITEM_H
3 // 此处是某个类的定义与相关函数定义
4 #endif

其中,条件指示#ifndef SALESITEM_H的作用是测试SALESITEM_H预处理器变量是否未定义。如果SALESITEM_H未定义,那么#ifndef测试成功,跟在#ifndef后面的所有行都被执行,直到发现#endif。相反,如果SALESITEM_H已定义,那么#ifndef指示测试为假,该指示和#endif指示间的代码都被忽略。

为了保证头文件在给定的源文件中只处理过一次,我们首先检测#ifndef。第一次处理头文件时,测试会成功,因为SALESITEM_H还未定义。下一条语句定义了SALESITEM_H。那样,如果我们编译的文件恰好又一次包含了该头文件,#ifndef指示会发现SALESITEM_H已经定义,并且忽略该头文件的剩余部分。

时间: 2024-11-08 22:31:59

【C/C++】C预处理器的相关文章

C预处理器

C预处理器是一种简单的宏处理器. 预处理器是由特殊的预处理器命令行控制的,它们是以#符号开头的源文件行. 预处理器的一般操作:从源文件中删除所有的预处理器命令行,并在源文件中执行这些预处理器命令所指定的转换操作 预处理器代码行的语法与C语言其他部分的语法是完全独立的,但经过预处理所产生的源代码必须在上下文环境中合法 常见的预处理器命令: #define  定义一个预处理器宏   #undef     取消一个预处理器宏 #include   插入另一个源文件的文本 #if        测试一个

笔记3:预处理器-(2)宏定义

#define指令称为宏定义指令,通常用#define指令来定义一个宏用来代表其他东西的一个名字(如常量表达式等).通常来说预处理器会通过将宏的名字和它的定义存储在一起来响应#define指令.当这个宏在后面的程序中使用到时,预处理器会"扩展"宏,将宏替换为其定义值. 简单的宏 简单的宏的定义格式: #define 标识符 替换列表 如: #define DTE_LEN 80 #define TRUE 1 #define FALSE 0 #define PI 3.1415926 #de

第六篇:使用预处理器帮助调试

前言 你是否遇到过以下情况? 情况一:为了调试方便,代码中夹杂各种cout语句.当调试好了,把这些语句删了,运行“正式版”后,又发现新问题,只得把这些cout语句一个个添加回去再进行调试.如此不断循环. 情况二:希望在代码中获取到源文件的文件名,当前代码行号,编译时间等信息. 情况三:纠结于是否实现某些概率极低(几乎不存在)的错误检测 如果有,那么这篇随笔适合你,或者说,预处理器带来的调试技术适合你. 技巧一:设置调试区代码开关 请看下面的源代码: 1 #include <iostream>

关于前端CSS预处理器Sass的小知识!

前面的话 ??"CSS预处理器"(css preprocessor)的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件.SASS是一种CSS的开发工具,提 供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护.本文将详细介绍sass的使用 定义 ??Sass是一门高于CSS的元语言,它能用来清晰地.结构化地描述文件样式,有着比普通CSS更加强大的功能.Sass能够提供更简洁.更优雅的语法,同时提供多种功能来创建可维护和管理的样式

预处理器

本文是对C++预处理器的学习整理,参考了网站www.learncpp.com相关章节的内容. 一.概述 代码在编译之前需要通过预处理器进行预处理,预处理器运行时,逐行扫描代码寻找预处理指令.预处理指令是以#开头.换行符结尾(不是分号:)的代码. 预处理器主要实现一下三个功能: 1. include 2. macro define 宏定义. 3. 条件编译 二.include 故名思意,#include用于包含头文件,预处理器在遇到#include 指令时,将相应头文件的内容复制到指令所在的位置.

C语言难点2之预处理器

C语言难点2之预处理器 1 预处理阶段 在预处理阶段中,C预处理器在源代码编译之前对其进行一些文本性质的操作.它的主要任务包括删除注释,插入被#include指定包含的文件的内容,定义和替换由#define指令定义的符号一起确定代码的部分内容是否应该根据一些条件编译指令进行编译. 2 #define命令 采用宏定义时候的易错点: 格式: #define  name  stuff 有了这条指令之后,每当有符号name出现在这条指令后面时,预处理器就会把它替换成stuff. 注意:宏定义后面不能加上

C Primer Plus之C预处理器和C库

编译程序前,先由预处理器检查程序(因此称为预处理器).根据程序中使用的预处理器指令,预处理器用符号缩略语所代表的内容替换程序中的缩略语. 预处理器不能理解C,它一般是接受一些文件并将其转换成其他文本. 翻译程序的第一步 对程序作预处理前,编译器会对它进行几次翻译处理. 编译器首先把源代码中出现的字符映射到源字符集(?).该过程处理多字节字符和使C外观更加国际化的三元字符(?)扩展 编译器查找反斜线(\)后紧跟换行符的实例并删除这些实例.注意:在这种场合下,“换行符”代表按下回车键在源代码文件中新

C Primer Plus读书笔记-预处理器指令

代码中经常看到  #define ,#ifdef #define :明显常量 一般的指令长度仅限与一行代码,除了\(反斜杠线)可以拓展到下一行外. 一般情况下,每个#define行由三个部分组成. 第一部分为#define 指令本身 第二部分为所选择的缩略语,这些缩略语称为宏(macro).  宏的名字中不允许有空格!只能使用字母,下划线(_),和数字之间的组合,第一个字符不能为数字 第三部分(#define行除了第一第二部分外的部分).称为替换列表或主体. 预处理器在程序中发现宏的实例后,总会

C和C++的面向对象专题(8)——更为高级的预处理器PHP

本专栏文章列表 一.何为面向对象 二.C语言也能实现面向对象 三.C++中的不优雅特性 四.解决封装,避免接口 五.合理使用模板,避免代码冗余 六.C++也能反射 七.单例模式解决静态成员对象和全局对象的构造顺序难题 八.更为高级的预处理器PHP 八.更为高级的预处理器PHP C++的宏在某些情况下非常难用,例如将代码展开成为这样: Macro( A, B, C, D ) => func("A", A); func("B", B); func("C&