栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言学习记录:宏定义:#define

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言学习记录:宏定义:#define

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

预处理指令示例:

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

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


目录

#define

记号问题

类函数宏

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

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

变参宏:...和__VA_ARGS__


#define

程序示例:

以下定义都是被允许的!

#include 
#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("%sn",OW);     //这里输出的是代表的字符串!
    printf("TWO:OWn");    //这里输出的是: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 ,但是实际上是 23

X = 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 ## n

XNAME(4)   //被编译器解释为x4 

## 作为黏合剂的使用:

#define XNAME(n) x ## n
#define PRINT(n) printf("X" #n " = %dn",x ## n);

int main(void)
{
    int XNAME(1) = 14;    //解释为 int x1 = 14;
    int XNAME(2) = 20;
    int x3 = 30;
    PRINT(1);             //解释为 printf("x1 = %dn",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 
#include 

#define PR(X,...) printf("Message " #X ": "__VA_ARGS__)

int main(void)
{
    double x = 48;
    double y;        //y没定义是乱数
    
    y = sqrt(x);
    PR(1,"x = %gn",x);                //printf("Message 1:x = %gn",x);
    PR(2,"x= %.2f, y = %.4fn",x,y);

    return 0;
}

输出:

Message 1: x = 48

Message 2: x = 48.00, y = 6.9282

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/917443.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号