C预处理器:在程序执行之前查看程序。根据程序中的预处理器指令,预处理器把符号缩写替换成其表示的内容。

预处理指令示例:

#define、#include、#ifdef、#else、#endif、#ifndef、#if、#elif、#line、#error、#pragma

ANSI和后来的标准都允许 # 前面有空格或者制表符,而且还允许在 # 和指令的其余部分之间有空格。


目录

#define

记号问题

类函数宏

用宏参数创建字符串:#运算符

预处理器黏合剂:##运算符

变参宏:...和__VA_ARGS__


#define

程序示例:

以下定义都是被允许的!

#include <stdio.h>
#define TWO 2
#define OW "Consistency is the last refuge of the unimagina\
tive. -Oscar Wilde"                    //反斜杠表示切换到下一行
#define FOUR = TWO*TWO
#define PX printf("X is %d.\n",x)
#define FMT "X is %d.\n"int main(void)
{    int x = TWO;PX;x = FOUR;printf(FMT,x);printf("%s\n",OW);     //这里输出的是代表的字符串!printf("TWO:OW\n");    //这里输出的是:TWO:OW,而不是其代表的字符串和数组!
}

拿出一个逻辑行当例子说明:

#define TWO 2

#define 是预处理器指令,TWO 是选定的缩写,也成为2 称为替换列表或替换体。

有些宏代表值,称为类对象宏(object-like macro),还有类函数宏(function-like macro)

在宏定义中,还可以包含其他宏。


记号问题

把宏的替换体看做是记号(token)型字符串,而不是字符型字符串。

#define FOUR 2*2

只有一个记号:2*2 序列

#define SIX 2 * 3

这个宏定义有三个记号:2*3

假设编译器解释为字符型字符串,将用 2 * 3 替换 SIX 。即额外的空格是替换体的一部分。

编译器解释为记号型字符串,则用3个的记号 2 * 3 (分别由单个空格分隔)来替换 SIX 。

解释为字符型字符串:把空格视为替换体的一部分。解释为记号型字符串:把空格视为替换体中各记号的分隔符。


类函数宏

在 #define 中使用参数可以创建外形和作用与函数类似的类函数宏。参数称为宏参数。

例子:

#define SQUIRE(x) x*x#define SUM(x,y) x+y//调用sum = SUM(5,7);
squire = SQUIRE(9);

但是,函数宏只是替换并不是真正的函数!

//列如
SQUIRE(2+7)
//理想中应该是 81 ,但是实际上是 23X = 100/SQUIRE(2)
//理想中应该是 25 ,但是实际上是 100

为什么出现这种状况?实际上的计算过程:

SQUIRE(2+7) = 2+7*2+7 = 23

X =100/SQUIRE(2) = 100/2*2 = 100

编程时应注意

#define SQUIRE(x) ((x)*(x))

用宏参数创建字符串:#运算符

引入例子:

#define PSQR(X) printf("The squire of X is %d.\n",((x)*(x)));
//使用宏:
PSQR(9);//输出
The squire of X is 81.\n

此时 "" 中的 X 被视作普通文本,而不是可替换的符号。

字符串化(stringizing)

#define PSQR(X) printf("The squire of " #X " is %d.\n",((X)*(X)));int main(void)
{int y = 5;PSQR(y);PSQR(2 + 4);return 0;
}

此时的输出为:

The squire of y is 25.

The squire of 2 + 4 is 36.


预处理器黏合剂:##运算符

与 # 运算符类似, ## 运算符可用于 类函数宏 的替换部分。而且, ## 还可以用于对象宏的替换部分。 ## 运算符把两个记号组成为一个记号。

such as:

#define XNAME(n) x ## nXNAME(4)   //被编译器解释为x4 

## 作为黏合剂的使用:

#define XNAME(n) x ## n
#define PRINT(n) printf("X" #n " = %d\n",x ## n);int main(void)
{int XNAME(1) = 14;    //解释为 int x1 = 14;int XNAME(2) = 20;int x3 = 30;PRINT(1);             //解释为 printf("x1 = %d\n",x1);PRINT(2);PRINT(3);return 0;
}

运行结果有:

x1 = 14

x2 = 20

x3 = 30

体会一下其中的含义吧 ~


变参宏:...和__VA_ARGS__

这个还是需要多考虑一下的!!

这个以前没注意过,读别人代码才发现有这么个东西,我真是沙雕了!

一些函数支持数量可变的参数。如printf() 。

用户可自定义带可变参数的函数,stdvar.h 头文件中提供了工具。

通过把宏参数列表中的最后的参数写成省略号来实现这一功能。这样,预定义宏__VA_ARGS__可用在替换部分中,表明省略号代表什么

#define PR(...) printf(__VA_ARGS__);

程序示例:

#include <stdio.h>
#include <math.h>#define PR(X,...) printf("Message " #X ": "__VA_ARGS__)int main(void)
{double x = 48;double y;        //y没定义是乱数y = sqrt(x);PR(1,"x = %g\n",x);                //printf("Message 1:x = %g\n",x);PR(2,"x= %.2f, y = %.4f\n",x,y);return 0;
}

输出:

Message 1: x = 48

Message 2: x = 48.00, y = 6.9282

省略符号只能代替最后的宏参数!!!!

最后,宏名中不允许出现空格!!!在嵌套循环中使用宏定义的函数有助于提高效率,单词循环看不出来效果。

C语言学习记录:宏定义:#define相关推荐

  1. C语言学习笔记-宏定义-SWAP交换两个变量值

    面试中经常考到的一个题.原理跟 a=a+b;   b=a-b;  a=a-b;  一样的,很简单,不解释. //宏定义 交换两个变量的值.使用异或运算. #define SWAP(a,b) {a=a^ ...

  2. C语言常用宏定义(#define)使用方法

    ·  正  ·  文  ·  来  ·  啦  · 前言 ------在上篇文章里面,我们分析了预处理的一个完整过程,这能够让我们理解一个写好的程序,在生成一个可执行文件,到底发生了什么,对我们在大型 ...

  3. C语言 | 预处理 | 宏定义 | #define | 定义函数

    文章目录 预处理 预处理运算符 宏定义 无参宏定义 带参宏定义 宏定义-定义函数 此文主要介绍宏定义,并在介绍宏定义时举例介绍预处理命令 预处理 参考:C 预处理器 | 菜鸟教程 重要的预处理器指令如 ...

  4. [C语言]宏定义#define的使用详解

    一.宏定义定义常量 预定义符号 FILE //进行编译的源文件 LINE //文件当前的行号 DATE //文件被编译的日期 TIME //文件被编译的时间 STDC //如果编译器遵循ANSI C, ...

  5. 宏定义Define的一些用法

    ---转载百度文库 一. #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处 ...

  6. 宏定义#define整理

    一.宏定义#define 优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率.代码可以写的通俗易懂.可以提高程序的清晰性.可读性,使于修改移植等. 缺点:宏定义的使用实 ...

  7. VS无法使用宏定义#define解决方案

    在使用VS编译C语言或者其他语音用到宏定义#define,VS会报错提示(以VS2019为例) 解决方式: 在工具-->选项-->文本编辑器-->C/C++-->查看中,将&q ...

  8. 预处理命令 宏定义 #define #undef

    预处理命令 源程序中以#开头的行称为预处理指令. 预处理指令并不是C语言的语法成分,而是传给编译程序的指令. 包括: 宏定义 #define #undef 文件包含 #include 条件编译 #if ...

  9. 枚举(enum)、宏定义(#define)、结构体(struct)的拾遗

    1.宏定义 1.1.不带参数的宏定义 #define 标识符 字符串           例如:#define PI 3.1415926 说明: (1)宏名一般习惯用大写字母表示,但并非规定,也可以用 ...

  10. python语言学习:python语言学习中的定义类、定义函数、封装api等详细攻略

    python语言学习:python语言学习中的定义类.定义函数.封装api等详细攻略 目录 python语言学习中的定义类 python语言学习中的定义函数 python语言学习中封装api pyth ...

最新文章

  1. C#+AE 调整TOCControl控件中图层的显示顺序
  2. WCF之自定义信道工厂,信道监听器
  3. 手动添加JAR包到本地Maven仓库
  4. F5打造“感知可控,随需而变的应用”  助力企业实现非凡数字体验
  5. 关于liaoxuefeng的python3教程实战第四天
  6. 计算机网络学习笔记(7. 报文交换与分组交换①)
  7. 韩国遭 Lazarus Group 供应链攻击
  8. OpenGL 坐标变换(1)
  9. HDU1282 回文数猜想【回文】
  10. 如何定制 Calico 网络 Policy - 每天5分钟玩转 Docker 容器技术(70)
  11. 校内人气之星_专访丨人气之星金奖得主黄圣雯:我想成为更好的自己
  12. c语言编译器C11,如何检测c11支持编译器与cmake
  13. opengl 加载obj模型
  14. 检索报告计算机类,计算机类的检索报告.docx
  15. 循环冗余校验码例题[转帖]
  16. PCIe系列第三讲、事务层通用 TLP 头结构分析
  17. C#WinForm实现对Excel的数据处理
  18. hackme1新手教学
  19. linux shell 笔记
  20. 新一代“四型机场”,青岛胶东国际机场正式实施转场运营

热门文章

  1. Google Play约会游戏开发者,ChinaJoy 2017完美收官!
  2. 收集K8S容器的标准输出日志实践
  3. 算法设计与分析——顺序统计量:期望为线性时间的选择算法
  4. 概率统计中的样本矩和顺序统计量
  5. 3DSMAX模型烘焙流程
  6. 资源推荐|347个Python开发经典资源推荐(42类)
  7. scikit-learn决策树
  8. Wine 的QQ,微信 中文显示与字体设置 - 显示为方框
  9. 联想笔记本关闭锁定计算机,联想笔记本锁定触控板的方法_联想笔记本怎么锁定触控板-win7之家...
  10. php婚礼请帖,结婚请柬上的浪漫句子 婚礼请帖唯美的句子