如何打印宏

1. 问题描述

我们都知道,在C/C++中经常会用到宏定义,宏实际上就是给一个字段取的一个别名,它是属于预编译系统的一部分,其形式如:

  1. #define PI 3.141592654

当我们想要使用3.141592654这个值的时候,直接用它的别名PI就可以了。如果什么时候,我们需要将PI的精度提高,则只需要修改这个宏定义就可以了,而不用一个一个的去修改。
同时,宏是没有类型的,在预编译时,系统对它只是完全的字符替换而已,例如:

  1. #define SQR(x) x*x
  2. int main()
  3. {
  4. int a=SQR(5+3);
  5. printf("the result is:%d",a);
  6. return 0;
  7. }

在预编译后,代码相当于:

  1. int main()
  2. {
  3. int a=5+3*5+3;
  4. printf("the result is:%d\n",a);
  5. return 0;
  6. }

结果是:the result is:23

因为宏是没有类型的,编译后只是简单字符的替换,那如果我想将PI以字符串的形式打印出来呢,该如何操作?
其实这还不好操作,直接将一个字符串取一个别名如:

  1. #define HELLO "hello World!"
  2. int main()
  3. {
  4. printf("the string is:%s",HELLO);
  5. return 0;
  6. }

结果是:the string is:hello World!
既然这样,那就再问一个问题,如果一开始你就跟本不知道定义的宏是个字符串形式呢?如:

  1. #define PI 3.141592654

我依然想将3.141592654打印出来,该如何操作呢?

2. 分析思路

需要将宏打印出来,其实就是将#define PI 3.141592654转换成#define PI “3.141592654”
在这里需要用到#符号,它是一个预处理运算法,作用是将语言符号转化成字符串。然后先来实验下:

  1. #include<stdio.h>
  2. #define PI 3.141592654
  3. #define str(s) #s
  4. int main()
  5. {
  6. printf("printf:%s\n",str(PI));
  7. return 0;
  8. }

然后进行预编译命令:
gcc -E test.c -o test.i
编译后得到的test.i文件就是预编译后的文件,打开查看里面有如下内容:

  1. int main()
  2. {
  3. printf("printf:%s\n","PI");
  4. return 0;
  5. }

我们要的是3.141592654,而不是PI字符串,所以需要再加个宏定义,具体如下:

  1. #include<stdio.h>
  2. #define PI 3.141592654
  3. #define xstr(s) str(s)
  4. #define str(s) #s
  5. int main()
  6. {
  7. printf("printf:%s\n",xstr(PI));
  8. return 0;
  9. }

同样按前面的方式进行预编译,得到的预编译文件大体如下:

  1. int main()
  2. {
  3. printf("printf:%s\n","3.141592654");
  4. return 0;
  5. }

通过它编译出来的程序,执行结果如下:

  1. user@user-Lenovo-Product:/local/sdb/tempFile/cTest$ ./test.o
  2. printf:3.141592654

3. 总结

这个问题也是无意中看到的,在解决一个问题时,当时是希望将宏写入到编译后的文件中(即编译后文件会分配空间并存储该宏的内容),具体如图所示:

然后发现有使用打印宏的这个功能,感觉比较有趣,做个笔记方便后面查询。