在Unix/Linux内核代码以及GNU libc源代码中,有两个C的宏被广泛使用。 例如:
/* glibc-2.25/sysdeps/powerpc/powerpc64/sysdep.h */
#define tostring(s) #s
#define stringify(s) tostring(s)
#define XGLUE(a,b) a##b
#define GLUE(a,b) XGLUE(a,b)
在gdb中用命令macro定义并展开看看,
(gdb) help macro
Prefix for commands dealing with C preprocessor macros. List of macro subcommands: macro define -- Define a new C/C++ preprocessor macro
macro expand -- Fully expand any C/C++ preprocessor macro invocations in EXPRESSION
macro expand-once -- Expand C/C++ preprocessor macro invocations appearing directly in EXPRESSION
macro list -- List all the macros defined using the `macro define' command
macro undef -- Remove the definition of the C/C++ preprocessor macro with the given name
...<snip>...
(gdb) #
(gdb) macro define tostring(s) #s
(gdb) macro define stringify(s) tostring(s)
(gdb) macro define XGLUE(a,b) a##b
(gdb) macro define GLUE(a,b) XGLUE(a,b)
(gdb) #
(gdb) macro list
macro define GLUE(a, b) XGLUE(a,b)
macro define XGLUE(a, b) a##b
macro define stringify(s) tostring(s)
macro define tostring(s) #s
(gdb) #
(gdb) macro expand tostring()
expands to: ""
(gdb) macro expand tostring("hello")
expands to: "\"hello\""
(gdb) #
(gdb) macro expand GLUE(, )
expands to:
(gdb) macro expand GLUE("hello", "world")
expands to: "hello""world"
由此可见,
- #是将单个宏参数转换成一个字符串
- ##则是将两个宏参数连接在一起
可以简记为“单#字符串,双#连接参”。
另外,也可以用"gcc -E"查看宏展开。例如,
$ cat foo.S
#define SYS_ify(syscall_name) __NR_##syscall_name
#define __NR_mmap 115
#define __NR_munmap 117 mov $SYS_ify(mmap), %eax
mov $SYS_ify(munmap), %eax $ gcc -E foo.S | tail -
mov $, %eax
mov $, %eax
$