用gdb理解C宏(#和##)
在Unix/Linux内核代码以及GNU libc源代码中,有两个C的宏被广泛使用。 例如:
/* glibc-2.25/sysdeps/powerpc/powerpc64/sysdep.h */ 207 #define tostring(s) #s 208 #define stringify(s) tostring(s) 209 #define XGLUE(a,b) a##b 210 #define GLUE(a,b) XGLUE(a,b)
在gdb中用命令macro定义并展开看看,
1 (gdb) help macro 2 Prefix for commands dealing with C preprocessor macros. 3 4 List of macro subcommands: 5 6 macro define -- Define a new C/C++ preprocessor macro 7 macro expand -- Fully expand any C/C++ preprocessor macro invocations in EXPRESSION 8 macro expand-once -- Expand C/C++ preprocessor macro invocations appearing directly in EXPRESSION 9 macro list -- List all the macros defined using the `macro define' command 10 macro undef -- Remove the definition of the C/C++ preprocessor macro with the given name 11 ...<snip>... 12 (gdb) # 13 (gdb) macro define tostring(s) #s 14 (gdb) macro define stringify(s) tostring(s) 15 (gdb) macro define XGLUE(a,b) a##b 16 (gdb) macro define GLUE(a,b) XGLUE(a,b) 17 (gdb) # 18 (gdb) macro list 19 macro define GLUE(a, b) XGLUE(a,b) 20 macro define XGLUE(a, b) a##b 21 macro define stringify(s) tostring(s) 22 macro define tostring(s) #s 23 (gdb) # 24 (gdb) macro expand tostring(12345) 25 expands to: "12345" 26 (gdb) macro expand tostring("hello") 27 expands to: "\"hello\"" 28 (gdb) # 29 (gdb) macro expand GLUE(123, 45) 30 expands to: 12345 31 (gdb) macro expand GLUE("hello", "world") 32 expands to: "hello""world"
由此可见,
- #是将单个宏参数转换成一个字符串
- ##则是将两个宏参数连接在一起
可以简记为“单#字符串,双#连接参”。
另外,也可以用"gcc -E"查看宏展开。例如,
1 $ cat foo.S 2 #define SYS_ify(syscall_name) __NR_##syscall_name 3 #define __NR_mmap 115 4 #define __NR_munmap 117 5 6 mov $SYS_ify(mmap), %eax 7 mov $SYS_ify(munmap), %eax 8 9 $ gcc -E foo.S | tail -2 10 mov $115, %eax 11 mov $117, %eax 12 $