C语言:预处理

1.#运算符

当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

复制代码
#include <stdio.h>
#define PRINT(n) printf("the value of n is %d", n);
int main()
{
	int a = 10;
	PRINT(a);
	return 0;
}

就像这段代码中,printf中的第一个n是不会被宏代替的,但我们想说明的是a的值(也就是第一个n被替换后的结果)。那我们就可以使用#运算符。

接下来要说的#运算符所执⾏的操作可以理解为"字符串化"。

复制代码
#include <stdio.h>
#define PRINT(n) printf("the value of "#n " is %d", n);
int main()
{
	int a = 10;
	PRINT(a);
	return 0;
}

在这段代码中,a被带入到#n和n,因为#n的预处理(字符串化)使得语句变成了printf("the value of ""a" " is %d", a);几个字符串会自动连接在一起,所以就能将a打印出来了。

2.## 运算符

可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的⽂本⽚段创建标识符。 ## 被称

为记号粘合。这样的连接必须产⽣⼀个合法的标识符。否则其结果就是未定义的。这⾥我们想想,写⼀个函数求2个数的较⼤值的时候,不同的数据类型就得写不同的函数。

复制代码
int int_max(int x, int y)
{
 return x>y?x:y;
}
float float_max(float x, float y)
{
 return x>yx:y;
}

其实在c++中可以使用函数重载来解决,其实在c语言中也有不错的方法来实现。

复制代码
#define GENERIC_MAX(type) \
type type_max(type x, type y)\
{ \
 return (x>y?x:y); \
}

学了基本的预处理,有人可以会想使用以上方式去定义函数,但我们会发现每次定义出来的函数名都是type_max,这是因为编译器将这个看成一个整体,并不会将其中的type代入。

解决就需要用到## 运算符。

复制代码
type type##_max(type x, type y)\
{ \
 return (x>y?x:y); \
}

这样编译器就会先将type代入,再将这两段文本连接在一起。这样处理后我们就可以通过这个宏定义去定义很多类似的函数了。

3.命名约定
⼀般来讲函数的宏的使⽤语法很相似。所以语⾔本⾝没法帮我们区分⼆者。
那我们平时的⼀个习惯是:
(1)把宏名全部⼤写
(2)函数名不要全部⼤写
4.#undef
这条指令⽤于移除⼀个宏定义。
5.#if,#elif,#else
同条件语句中的用法,多出来一条使用的预编译命令(#endif)。#endif表示这个if的条件编译的结束。
6.#ifdef,#ifndef
#ifdef判断的是是否定义,是为真,否为假,而#ifndef正好相反。#endif和前面一样表示条件编译的结束。在头文件中使用这些判断是否定义的预处理命令可以防止我们重复包含头文件,当然#pragma once也可以实现这个功能。
7.头⽂件的包含
双引号包含头文件一般用于用户头文件,会先在当前文件夹中寻找,再去标准路径中查找。而三角包含头文件一般用于库文件,会直接去标准路径中查找,库函数基于性能的考虑会选择这种包含方式。

相关推荐
2601_949146539 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
知南x11 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
2的n次方_13 小时前
Runtime 执行提交机制:NPU 硬件队列的管理与任务原子化下发
c语言·开发语言
凡人叶枫14 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
凡人叶枫15 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
傻乐u兔16 小时前
C语言进阶————指针3
c语言·开发语言
CodeSheep程序羊18 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
I'mChloe18 小时前
PTO-ISA 深度解析:PyPTO 范式生成的底层指令集与 NPU 算子执行的硬件映射
c语言·开发语言
2的n次方_18 小时前
Runtime 内存管理深化:推理批处理下的内存复用与生命周期精细控制
c语言·网络·架构
嵌入小生00718 小时前
标准IO---核心函数接口延续(嵌入式Linux)
c语言·vscode·vim·嵌入式·小白·标准io·函数接口