首页 > 代码库 > gcc编译期打印宏的值
gcc编译期打印宏的值
如果我们想知道一个宏的值应该怎么办?
要么在代码里加一句printf
要么在编译的时候gcc -E
第一种方法需要程序运行起来,颇为麻烦
第二种方法无法应付下面这些情况
比如宏的值等于sizeof(struct xxoo)
比如宏本身就是一个复杂的运算(((2U) << (((0+8)+8)+13)) | (((‘W‘)) << (0+8)) | (((7)) << 0) | (((((sizeof(int) == sizeof(int[1]) && sizeof(int) < (1 << 13)) ? sizeof(int) : __invalid_size_argument_for_IOC))) << ((0+8)+8)))
我设计了一个编译期打印宏值的方法,原理是利用gcc函数属性扩展warning和编译期运算
代码show_marco.h
#ifndef _SHOW_MACRO_H_ #define _SHOW_MACRO_H_ /* SHOW_MSG(expression, true string, false string) SHOW_MACRO(NAME) MACRO2STRING(NAME) zhaoxiaogang 2014-11-18 */ #define MACRO2STRING_(M) #M #define MACRO2STRING(M) MACRO2STRING_(M) #define a_t_t_r(S) __attribute__((warning(S))) #define SHOW_MSG__(E, S1, S2, L, N) int line__##L(void) a_t_t_r(S1); int LINE__##L(void) a_t_t_r(S2); int C##N##__LINE##L(void) { return (E) ? line__##L() : LINE__##L(); } #define SHOW_MSG_(E, S1, S2, L, N) SHOW_MSG__(E, S1, S2, L, N) #ifndef __COUNTER__ #define __COUNTER__ 0 #endif #define SHOW_MSG(E, S1, S2) SHOW_MSG_(E, S1, S2, __LINE__, __COUNTER__) #define j_(v) int show__0x##v(void) a_t_t_r(#v); j_(0) j_(1) j_(2) j_(3) j_(4) j_(5) j_(6) j_(7) j_(8) j_(9) j_(a) j_(b) j_(c) j_(d) j_(e) j_(f) #define k_(M,i,j) (((((M)+0ULL)>>((15-0x##i)*4))&0xF)==0x##j ? show__0x##j() : 0) + #define SHOW_MACRO(M) int M##__eq(void) a_t_t_r(#M" = "MACRO2STRING(M)); int M##__lt(void) a_t_t_r(#M" < 0"); int M##__ge(void) a_t_t_r(#M" >= 0"); int show__##M(void) { return M##__eq() + k_(M,0,0) k_(M,0,1) k_(M,0,2) k_(M,0,3) k_(M,0,4) k_(M,0,5) k_(M,0,6) k_(M,0,7) k_(M,0,8) k_(M,0,9) k_(M,0,a) k_(M,0,b) k_(M,0,c) k_(M,0,d) k_(M,0,e) k_(M,0,f) k_(M,1,0) k_(M,1,1) k_(M,1,2) k_(M,1,3) k_(M,1,4) k_(M,1,5) k_(M,1,6) k_(M,1,7) k_(M,1,8) k_(M,1,9) k_(M,1,a) k_(M,1,b) k_(M,1,c) k_(M,1,d) k_(M,1,e) k_(M,1,f) k_(M,2,0) k_(M,2,1) k_(M,2,2) k_(M,2,3) k_(M,2,4) k_(M,2,5) k_(M,2,6) k_(M,2,7) k_(M,2,8) k_(M,2,9) k_(M,2,a) k_(M,2,b) k_(M,2,c) k_(M,2,d) k_(M,2,e) k_(M,2,f) k_(M,3,0) k_(M,3,1) k_(M,3,2) k_(M,3,3) k_(M,3,4) k_(M,3,5) k_(M,3,6) k_(M,3,7) k_(M,3,8) k_(M,3,9) k_(M,3,a) k_(M,3,b) k_(M,3,c) k_(M,3,d) k_(M,3,e) k_(M,3,f) k_(M,4,0) k_(M,4,1) k_(M,4,2) k_(M,4,3) k_(M,4,4) k_(M,4,5) k_(M,4,6) k_(M,4,7) k_(M,4,8) k_(M,4,9) k_(M,4,a) k_(M,4,b) k_(M,4,c) k_(M,4,d) k_(M,4,e) k_(M,4,f) k_(M,5,0) k_(M,5,1) k_(M,5,2) k_(M,5,3) k_(M,5,4) k_(M,5,5) k_(M,5,6) k_(M,5,7) k_(M,5,8) k_(M,5,9) k_(M,5,a) k_(M,5,b) k_(M,5,c) k_(M,5,d) k_(M,5,e) k_(M,5,f) k_(M,6,0) k_(M,6,1) k_(M,6,2) k_(M,6,3) k_(M,6,4) k_(M,6,5) k_(M,6,6) k_(M,6,7) k_(M,6,8) k_(M,6,9) k_(M,6,a) k_(M,6,b) k_(M,6,c) k_(M,6,d) k_(M,6,e) k_(M,6,f) k_(M,7,0) k_(M,7,1) k_(M,7,2) k_(M,7,3) k_(M,7,4) k_(M,7,5) k_(M,7,6) k_(M,7,7) k_(M,7,8) k_(M,7,9) k_(M,7,a) k_(M,7,b) k_(M,7,c) k_(M,7,d) k_(M,7,e) k_(M,7,f) k_(M,8,0) k_(M,8,1) k_(M,8,2) k_(M,8,3) k_(M,8,4) k_(M,8,5) k_(M,8,6) k_(M,8,7) k_(M,8,8) k_(M,8,9) k_(M,8,a) k_(M,8,b) k_(M,8,c) k_(M,8,d) k_(M,8,e) k_(M,8,f) k_(M,9,0) k_(M,9,1) k_(M,9,2) k_(M,9,3) k_(M,9,4) k_(M,9,5) k_(M,9,6) k_(M,9,7) k_(M,9,8) k_(M,9,9) k_(M,9,a) k_(M,9,b) k_(M,9,c) k_(M,9,d) k_(M,9,e) k_(M,9,f) k_(M,a,0) k_(M,a,1) k_(M,a,2) k_(M,a,3) k_(M,a,4) k_(M,a,5) k_(M,a,6) k_(M,a,7) k_(M,a,8) k_(M,a,9) k_(M,a,a) k_(M,a,b) k_(M,a,c) k_(M,a,d) k_(M,a,e) k_(M,a,f) k_(M,b,0) k_(M,b,1) k_(M,b,2) k_(M,b,3) k_(M,b,4) k_(M,b,5) k_(M,b,6) k_(M,b,7) k_(M,b,8) k_(M,b,9) k_(M,b,a) k_(M,b,b) k_(M,b,c) k_(M,b,d) k_(M,b,e) k_(M,b,f) k_(M,c,0) k_(M,c,1) k_(M,c,2) k_(M,c,3) k_(M,c,4) k_(M,c,5) k_(M,c,6) k_(M,c,7) k_(M,c,8) k_(M,c,9) k_(M,c,a) k_(M,c,b) k_(M,c,c) k_(M,c,d) k_(M,c,e) k_(M,c,f) k_(M,d,0) k_(M,d,1) k_(M,d,2) k_(M,d,3) k_(M,d,4) k_(M,d,5) k_(M,d,6) k_(M,d,7) k_(M,d,8) k_(M,d,9) k_(M,d,a) k_(M,d,b) k_(M,d,c) k_(M,d,d) k_(M,d,e) k_(M,d,f) k_(M,e,0) k_(M,e,1) k_(M,e,2) k_(M,e,3) k_(M,e,4) k_(M,e,5) k_(M,e,6) k_(M,e,7) k_(M,e,8) k_(M,e,9) k_(M,e,a) k_(M,e,b) k_(M,e,c) k_(M,e,d) k_(M,e,e) k_(M,e,f) k_(M,f,0) k_(M,f,1) k_(M,f,2) k_(M,f,3) k_(M,f,4) k_(M,f,5) k_(M,f,6) k_(M,f,7) k_(M,f,8) k_(M,f,9) k_(M,f,a) k_(M,f,b) k_(M,f,c) k_(M,f,d) k_(M,f,e) k_(M,f,f) ((M) < 0 ? M##__lt() : M##__ge()); } #endif
用法举例
在要打印的源文件中加入
#include "show_macro.h"
SHOW_MACRO(WDIOC_GETTIMEOUT)
这样WDIOC_GETTIMEOUT的值就会以编译warning的形式打印出来
octeon-wdt-main.c:618: In function ‘show__WDIOC_GETTIMEOUT‘:
octeon-wdt-main.c:618: warning: call to ‘WDIOC_GETTIMEOUT__eq‘ declared with attribute warning: WDIOC_GETTIMEOUT = (((2U) << (((0+8)+8)+13)) | (((‘W‘)) << (0+8)) | (((7)) << 0) | (((((sizeof(int) == sizeof(int[1]) && sizeof(int) < (1 << 13)) ? sizeof(int) : __invalid_size_argument_for_IOC))) << ((0+8)+8)))
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x4‘ declared with attribute warning: 4
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x4‘ declared with attribute warning: 4
octeon-wdt-main.c:618: warning: call to ‘show__0x5‘ declared with attribute warning: 5
octeon-wdt-main.c:618: warning: call to ‘show__0x7‘ declared with attribute warning: 7
octeon-wdt-main.c:618: warning: call to ‘show__0x0‘ declared with attribute warning: 0
octeon-wdt-main.c:618: warning: call to ‘show__0x7‘ declared with attribute warning: 7
octeon-wdt-main.c:618: warning: call to ‘WDIOC_GETTIMEOUT__ge‘ declared with attribute warning: WDIOC_GETTIMEOUT >= 0
0x0000000040045707就是WDIOC_GETTIMEOUT的值
注意,如果编译信息太多,那么可能需要筛选一下 gcc ... -c octeon-wdt-main.c 2>&1 | grep warning
另外, show_macro.h还附送了一个叫 SHOW_MSG(exp, str1, str2) 的宏
当exp为真时编译时打印字符串str1否则打印str2
gcc编译期打印宏的值