Loading

编译预处理

 

# 开头的是编译预处理指令,编译器开始编译之前,编译预处理程序(cpp)会把程序中的名字换成值,这是完全的文本替换

#define <名字> <值> 

注意没有结尾的分号,因为不是 C 的语句。名字必须是⼀个单词,值可以是各种东西。

如果一个宏的值中有其他的宏的名字,也是会被替换的

#define PI 3.14
#define PI2 2*PI

如果一个宏的值超过一行,最后一行之前的行末需要加 \

#define PRT printf("Hello");  \
            printf("World")

宏的值后面出现的注释不会被当作宏的值的一部分

#define PI 3.14 // 定义圆周率

 

常用语法

下面是常用的几个宏指令,它们可以直接在代码中使用

#if 		// 如果表达式为真,执行代码
#else 		// 如果 #if 表达式为假,执行代码
#elif 		// 相当于 else if
#endif 		// 用来标志一个条件指令的结束
#ifedf 		// 如果本指令所引用的定义已存在,执行代码
#ifndef 	// 如果本指令所引用的定义不存在,执行代码
#include 	// 一个编译预处理指令,和宏一样,在编译之前就处理了,它把那个文件的全部文本内容原封不动地插入到它所在的地方
#undef		// 取消宏定义

 

为了防止重复包含头文件,常在文件头尾添加宏定义

#ifndef LOVE_FISHC
#define LOVE_FISHC
	class FishC {...};
#endif

建议使用文件名作为宏名,例如对 math.h

#define __MATH_H

也可以使用

#pragma once

防止整个文件内容被重复包含(可能有兼容性问题)

在头文件中定义变量时,不仅要用编译预处理指令判断引用,最好还要使用 static const 来避免重复定义

 

特殊的宏

__cplusplus 	// 该宏在 C++ 文件中自动生成,表示这是 C++ 文件
__FILE__ 		// 当前文件名字符串
__LINE__ 		// 当前行号整型
__DATE__ 		// 日期字符串
__func__ 
__FUNCTION__ 	// 两者都表示当前执行的函数名字符串
__TIME__ 		// 时间字符串

例如我们可以输出当前函数名

printf("%s", __func__);

 

可以修改行号和原文件名

#line 行号 ["文件名"]

例如有时我们希望调整下一行的行号

#include <stdio.h>
 
#line 100 "macro-new.c" // 更改下一行的行号和源文件名
int main()              // line 100
{
    printf("%d\n", __LINE__); // line 102
    printf("%d\n", __LINE__); // line 103
    printf("%s\n", __FILE__);
    return 0;
}

 ​

带参数的宏

使用宏可以简化一些函数的书写

#define F(x) ((x)*(x)*(x))
printf(“%d”,F(5));

需要注意,宏是单纯的文本替换,因此

  • ⼀切都要括号
  • 整个值要括号
  • 参数出现的每个地方都要括号
posted @ 2022-03-17 18:13  Bluemultipl  阅读(142)  评论(0)    收藏  举报