C语言预处理指令的初步了解
所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。
C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等。合理地使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。
宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。在C语言中,“宏”分为有参数和无参数两种。
无参宏定义
无参宏的宏名后不带参数。其定义的一般形式为:
#define 标识符 字符串
其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。
注意以下几点:
1) 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作 任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。
2) 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。
3) 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。
4) 宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
5) 宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。
6) 习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母。
7) 可用宏定义表示数据类型,使书写方便。
应注意用宏定义表示数据类型和用typedef定义数据说明符的区别。宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简单的代换,而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。
#define PIN1 int *
typedef (int *) PIN2;
从形式上看这两者相似, 但在实际使用中却不相同。
下面用PIN1,PIN2说明变量时就可以看出它们的区别:
PIN1 a,b;
在宏代换后变成:
int *a,b;
表示a是指向整型的指针变量,而b是整型变量。然而:
PIN2 a,b;
表示a、b都是指向整型的指针变量。因为PIN2是一个类型说明符。由这个例子可见,宏定义虽然也可表示数据类型, 但毕竟是作字符代换。在使用时要分外小心,以避出错。
C语言预处理指令总结
预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
涉及到的部分预处理指令:
| 指令 | 说明 |
|---|---|
| # | 空指令,无任何效果 |
| #include | 包含一个源代码文件 |
| #define | 定义宏 |
| #undef | 取消已定义的宏 |
| #if | 如果给定条件为真,则编译下面代码 |
| #ifdef | 如果宏已经定义,则编译下面代码 |
| #ifndef | 如果宏没有定义,则编译下面代码 |
| #elif | 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码 |
| #endif | 结束一个#if……#else条件编译块 |
预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的。程序员在程序中用预处理命令来调用这些功能。
宏定义可以带有参数,宏调用时是以实参代换形参。而不是“值传送”。
为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。
文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。
条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。
使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计。
C语言预处理指令的初步了解的更多相关文章
- C语言预处理指令
C程序的源代码中可包括各种编译指令,这些指令称为预处理命令.虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境.本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性.ANS ...
- c语言学习之基础知识点介绍(九):预处理指令和多文件开发
一:预处理指令 /* 预处理指令: 作用:在程序编译之前做一些操作. 预处理命令写法的共同特点:都是以#号开头. 文件包含指令:#include 是一个文件包含命令. 作用:把某个文件内的内容读取出来 ...
- c语言的预处理指令分3种 1> 宏定义 2> 条件编译 3> 文件包含
宏简介 1.C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译 所有的预处 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#if 预处理指令
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#if 预处理指令 1.返回顶部 1. #if(C# 参考) 2018/06/30 如果 C# 编译器遇到 #if 指令,最终是 ...
- C语言系列之预处理指令、循环左移函数的使用(四)
本章节将讲两个知识点 第一个知识点:常用的预处理指令 第二个知识点:循环左移右移函数 第一个知识点:预处理指令 一种预处理指令是#define,他把名字A定义为P0,当这个名字出现在源文件的任何地方时 ...
- c语言学习之基础知识点介绍(二十):预处理指令
一.预处理指令的介绍 预处理命令:在编译之前触发的一系列操作(命令)就叫预处理命令. 特点:以#开头,不要加分号. #include: 文件包含指令 把指定文件的内容复制到相应的位置 #define: ...
- 从头开始-06.C语言中预处理指令
预处理指令 不带参数的宏定义: 格式: #define 宏名 值 作用:提高代码的可读性 在程序编译前把所有出现宏名标示的位置都替换为定义宏的时候,宏名后面的值 带参数的宏定义 格式 #define ...
- C语言-1.结构体,2.枚举,3.typedef,4.预处理指令的概念,5.条件编译
1. 结构体数组 定义:由若干个相同类型的结构体变量组成的有序的集合. 定义格式: 1) 定义结构体的同时定义结构体数组 struct Car{ int lunzi; int speed; }cars ...
- C语言基本语法——预处理器和预处理指令
1.什么是预处理器 2.什么是预处理器指令 3.预处理器指令 4.宏指令 5.宏函数 6.宏函数的优缺点 7.条件编译指令 1.什么是预处理器 • 预处理器是一个程序,用来处理源程序中的预处理指令. ...
随机推荐
- Net线程池设计
Net线程池设计 功能描述: 支持创建多个线程池,并统一管理 支持不同线程池的容量控制,以及最少活动线程的设置 支持不同线程池中活动线程的闲时设置,即线程空闲时间到期后即自动被回收 结构设计: Thr ...
- Lintcode--001(比较字符串)
比较两个字符串A和B,确定A中是否包含B中所有的字符.字符串A和B中的字符都是 大写字母 注意事项 在 A 中出现的 B 字符串里的字符不需要连续或者有序. 您在真实的面试中是否遇到过这个题? Yes ...
- 最牛B的编码套路 【转】
原文:http://blog.csdn.net/happydeer/article/details/17023229 最近,我大量阅读了Steve Yegge的文章.其中有一篇叫“Practicing ...
- 从客户端(txtNewsContent="<hr />")中检测到有潜在危险的 Request.Form 值。怎么办呀?
<system.web><httpRuntime requestValidationMode="2.0" executionTimeout="3600& ...
- Keil中LIB库的作用、生成与调用
LIB库有什么用,一个简单的例子就是Silicon Labs为C8051F单片机USB提供的USBXpress LIB库了,如USB发送数据.接收数据等,都是通用性很强的函数,但因为保密的原因,这个函 ...
- Delphi7下实现HTTP的Post操作 转
Delphi7下实现HTTP的Post操作 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Gra ...
- Windows下编译eXosip、osip,以及UAC和UAS的例子
今天开始了SIP开源库的学习,我选择了osip和eXosip,但是这两个库的编译使用有些麻烦,源码下来之后编译会出现很多问题,网上也没有找到完整的编译介绍,只能一步一步的找办法解决,最后终于编译成功! ...
- c语言typedef之数组运用
#include <stdio.h> #include <stdlib.h> typedef ];//int arr[4]取一个别名 arr b c就是int b[4] int ...
- PHP常用魔术方法(__invoke魔术方法)
<?php //文件名:index.php define('a',__DIR__); include '/IMooc/Loader.php'; spl_autoload_register('\\ ...
- hdu 5424 Rikka with Graph II(dfs+哈密顿路径)
Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so h ...