鸟语天空
C预处理器
post by:追风剑情 2020-3-17 10:16

预处理指令:#define、#include、#ifdef、#else、#endif、#ifndef、#if、#elif、#line、#error、#pragma

预处理器不做计算,不对表达式求值。它只进行文本替换。

宏定义还可以包含其他宏(一些编译器可能不支持这种嵌套功能)。

示例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>

// 可用反斜杠切换到下一行书写
#define ROW "this is tow row, \
i love you!"

// 定义函数宏
// SQUARE是宏标识符,X是宏参数,X*X是替换列表,程序中出现SQUARE(X)的地方都会被X*X替换。
#define SQUARE(X) X*X
// 注意: 避免在宏中出现递增或递减运算符++、--
// 例如,++x*++x,在C标准中并未规定这种情况的计算顺序,不同的编译器可能产生不同的计算结果。
#define PR(X) printf("The result is %d.\n", X)
// #x会被替换成宏参数
#define PSQR(x) printf("The square of " #x " is %d.\n", ((x)*(x)))
// 预处理器黏合剂:##运算符,把两个记号组合成一个记号
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d\n", x ## n)

int main(int argc, char* argv[])
{
	int x = 5;
	int z;
	int XNAME(1) = 14; // 变成 int x1 = 14;
	int XNAME(2) = 20; // 变成 int x2 = 20;
	int x3 = 30;
	PRINT_XN(1); // 变成 printf("x1 = %d\n", x1);
	PRINT_XN(2); // 变成 printf("x2 = %d\n", x2);
	PRINT_XN(3); // 变成 printf("x3 = %d\n", x3);

	printf("x = %d\n", x);
	z = SQUARE(x);
	printf("Evaluating SQUARE(x):");
	PR(z);
	z = SQUARE(2);
	printf("Evaluating SQUARE(2):");
	PR(z);
	printf("Evaluating SQUARE(x+2):");
	//宏调用在编译之前把参数记号传递给程序
	PR(SQUARE(x + 2));//因为预处理器不做计算,这里等价于PR(x+2*x+2)
	printf("Evaluating 100/SQUARE(2):");
	PR(100 / SQUARE(2));
	printf("x is %d.\n", x);
	printf("Evaluating SQUARE(++x): ");
	PR(SQUARE(++x));
	printf("After incrementing, x is %x.\n", x);
	PSQR(2+4);

	system("pause");
	return 0;
}


运行测试

1111.png

示例:预处理宏


//#pragma 设置编译器参数
//#pragma c9x on

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>

//条件编译
#ifdef MAVIS
//旧编译器代码块必须左对齐
#define STABLES 5
#else
//旧编译器代码块必须左对齐
#define STABLES 15
#endif

//#ifndef通常用来防止重复定义宏或重复包含头文件
//如果宏未定义
#ifndef SIZE
	//新编译器支持代码块缩进
	#define SIZE 100
#endif

//防止重复包含头文件
#ifndef HADE_H_
#define HEAD_H_
#endif

#if SYS == 1

#elif SYS == 2

#elif SYS == 3

#else

#endif

//较新编译器提供了defined()
//如果定义了IBMPC宏,defined()则返回1,否则返回0
#if defined (IBMPC)

#elif defined (VAX)

#elif defined (MAC)

#else

#endif

//空宏
#define EMPTY
#define LIMIT 400
//取消之前的#define LIMIT定义
#undef LIMIT

int main(int argc, char* argv[])
{
	//内置的预定义宏
	printf("__DATE__: %s\n", __DATE__); //输出时间 Mmm dd yyyy
	printf("__FILE__: %s\n", __FILE__); //输出当前代码文件路径
	printf("__LINE__: %d\n", __LINE__); //输出当前源代码行号
	//printf("__STDC__: %d", __STDC__); //1:遵循C标准
	printf("__STDC_HOSTED__: %d\n", __STDC_HOSTED__); //1:本机环境
	//printf("__STDC_VERSION__: %d\n", __STDC_VERSION__);//199901L:支持C99标准,201112L:支持C11标准
	printf("__TIME__: %s\n", __TIME__);//当前时间 hh:mm:ss
	printf("__func__: %s\n", __func__);

	//#line指令重置__LINE__和__FILE__宏报告的行号和文件名。
#line 1000 // 把当前行号重置为1000
#line 10 "cool.c" // 把行号重置为10,把文件名重置为cool.c

#if __STDC_VERSION__ != 201112l
//#error Not C11
#endif

	system("pause");
	return 0;
}


运行测试

111.png

示例:泛型选择(C11)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>

//泛型选择(C11)
//根据X的类型来匹配值
//例如,X是int类型,则返回"int"
#define MYTYPE(X) _Generic((X), \
	int : "int", \
	float: "float", \
	double: "double", \
	default: "other" \
)

int main(int argc, char* argv[])
{
	int d = 5;
	printf("%s\n", MYTYPE(d)); //输出"int"
	printf("%s\n", MYTYPE(2.0*d)); //输出"double"
	printf("%s\n", MYTYPE(3L)); //输出"other"
	printf("%s\n", MYTYPE(&d)); //输出"other"

	system("pause");
	return 0;
}

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容