#运算符用于在预编译期将宏参数转换为字符串
例1:
#include <stdio.h>
#define CONVERS(x) #x
int main()
{
printf("%s\n", CONVERS(Hello world!));
printf("%s\n", CONVERS(100));
printf("%s\n", CONVERS(while));
printf("%s\n", CONVERS(return));
return 0;
}
预编译后生成如下
int main()
{
printf("%s\n", "Hello world!");
printf("%s\n", "100");
printf("%s\n", "while");
printf("%s\n", "return");
return 0;
}
编译运行结果如下
例2:
#include <stdio.h>
#define CALL(f, p) (printf("Call function %s\n", #f), f(p))
int square(int n)
{
return n * n;
}
int f(int x)
{
return x;
}
int main()
{
printf("1. %d\n", CALL(square, 4));
printf("2. %d\n", CALL(f, 10));
return 0;
}
经过预编译生成如下
int square(int n)
{
return n * n;
}
int f(int x)
{
return x;
}
int main()
{
printf("1. %d\n", (printf("Call function %s\n", "square"), square(4))); //划线处是逗号表达式
printf("2. %d\n", (printf("Call function %s\n", "f"), f(10)));
return 0;
}
编译运行输出
调用函数之前,先把函数名打印出来,然后在调用函数把结果打印出来
这里体现了宏的强大,能打印出外边的函数名,用函数是做不到这一点的,因为#只能在宏里面使用
##运算符
##运算符用于在预编译期粘连两个符号
例3:
#include <stdio.h>
#define NAME(n) name##n
int main()
{
int NAME(1);
int NAME(2);
NAME(1) = 1;
NAME(2) = 2;
printf("%d\n", NAME(1));
printf("%d\n", NAME(2));
return 0;
}
预编译生成
int main()
{
int name1;
int name2;
name1 = 1;
name2 = 2;
printf("%d\n", name1);
printf("%d\n", name2);
return 0;
}
编译输出
利用##定义结构体类型:
#include <stdio.h>
#define STRUCT(type) typedef struct _tag_##type type;\
struct _tag_##type
STRUCT(Student)
{
char* name;
int id;
};
int main()
{
Student s1;
Student s2;
s1.name = "s1";
s1.id = 0;
s2.name = "s2";
s2.id = 1;
printf("%s\n", s1.name);
printf("%d\n", s1.id);
printf("%s\n", s2.name);
printf("%d\n", s2.id);
return 0;
}
预编译后生成
typedef struct _tag_Student Student;struct _tag_Student
{
char* name;
int id;
};
int main()
{
Student s1;
Student s2;
s1.name = "s1";
s1.id = 0;
s2.name = "s2";
s2.id = 1;
printf("%s\n", s1.name);
printf("%d\n", s1.id);
printf("%s\n", s2.name);
printf("%d\n", s2.id);
return 0;
}
需要说明的是,C语言可以先typedef然后在定义,只要在某处最终把struct定义出来后,无论在任何地方都可以重新typedef,并不是必须先定义struct再typedef
#define STRUCT(type) typedef struct _tag_##type type;\
struct _tag_##type
STRUCT(Student)
{
char* name;
int id;
};
此处很巧妙的用了##达到了一个新的“关键字”STRUCT,用STRUCT可以定义结构体,相当于扩展了C语言
这个例子也充分的展示了宏很强大,函数是没有办法实现它所有功能的