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.头⽂件的包含
双引号包含头文件一般用于用户头文件,会先在当前文件夹中寻找,再去标准路径中查找。而三角包含头文件一般用于库文件,会直接去标准路径中查找,库函数基于性能的考虑会选择这种包含方式。

相关推荐
天桥下的卖艺者1 小时前
R语言手搓一个计算生存分析C指数(C-index)的函数算法
c语言·算法·r语言
Yurko132 小时前
【C语言】基本语法结构(上篇)
c语言·开发语言·学习
小糖学代码4 小时前
Linux:11.线程概念与控制
linux·服务器·c语言·开发语言·c++
Kratzdisteln9 小时前
【C语言】Dev-C++如何编译C语言程序?从安装到运行一步到位
c语言·c++
Doro再努力10 小时前
数据结构04:力扣顺序表3道例题解题思路与代码实现
c语言·数据结构
疯狂吧小飞牛11 小时前
Lua C API 中的注册表介绍
java·c语言·lua
疯狂吧小飞牛14 小时前
Lua C API 中一段LUA建表过程解释
c语言·junit·lua
potato_may15 小时前
第18讲:C语言内存函数
c语言·数据结构·算法
顾晨阳——15 小时前
C/C++字符串
c语言·c++·字符串
Nix Lockhart16 小时前
《算法与数据结构》第七章[算法4]:最短路径
c语言·数据结构·学习·算法·图论