C语言预处理包括:宏定义、文件包含、条件编译等;预处理命令都以#开头:宏(#define)、文件包含(#include)、条件编译(#ifdef或#ifndef)。
本节主要分析宏定义的特殊用法。
一、#与##
1.#
#符号用作一个预处理运算符,它可以把语言符号转换成字符串。
eg:x是一个宏参数,那么#x可以把参数名转换成相应的字符串,这个过程叫字符串化。
test1.c
[cpp]
view plain
copy
- #include <stdio.h>
- #define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))
- int main(void)
- {
- int y =4;
- PSQR(y);
- PSQR(2+4);
- return 0;
- }
- /*result:
- the square ofyis 16.
- the square of2+4is 36.
- */
./test1
[plain]
view plain
copy
- the square ofyis 16.
- the square of2+4is 36.
该运算符把两个语言符号组合成单个语言符号。
test2.c
[cpp]
view plain
copy
- #include <stdio.h>
- #define XNAME(n) x##n
- #define PXN(n) printf("x"#n" = %d\n",x##n)
- int main(void)
- {
- int XNAME(1)=12;//int x1=12;
- PXN(1);//printf("x1 = %d\n", x1);
- return 0;
- }
- /*result:
- x1 = 12
- */
./test2
[plain]
view plain
copy
- x1 = 12
__VA_ARGS__是一个可变参数宏,是新的C99规范中新增的,目前只有gcc支持(VC6.0的编译器不支持)。
宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所代表的字符串。
简单例子:
test3.c
[cpp]
view plain
copy
- #include <stdio.h>
- #define PR(...) printf(__VA_ARGS__)
- int main()
- {
- int wt=1,sp=2;
- PR("hello\n");
- PR("weight = %d, shipping = %d\n",wt,sp);
- return 0;
- }
- /*result:
- hello
- weight = 1, shipping = 2
- */
./test3
[plain]
view plain
copy
- hello
- weight = 1, shipping = 2
公共接口:
common.h(相当与内核中的systemcalls.h)
[cpp]
view plain
copy
- #define __SC_DECL1(t1, a1) t1 a1
- #define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
- #define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
- #define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)
- #define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)
- #define __SYSCALL_DEFINEx(x, name, ...) \
- long sys##name(__SC_DECL##x(__VA_ARGS__))
- #define SYSCALL_DEFINEx(x, sname, ...) \
- __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
- #define SYSCALL_DEFINE0(name) long sys_##name(void)
- #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
test4.c
[cpp]
view plain
copy
- #include <stdio.h>
- #include "common.h"
- long sys_tank(void);
- long sys_tankai(void);
- SYSCALL_DEFINE0(tank)
- {
- printf("TK--------_>>>>>>tank call ok!!!\n");
- }
- SYSCALL_DEFINE0(tankai)
- {
- printf("TK--------_>>>>>>tankai call ok!!!\n");
- }
- int main(){
- sys_tank();
- sys_tankai();
- return 0;
- }
- /*result:
- TK----->>>lianjie(a,b) is 20
- TK----->>>lianjie(4,5) is 45
- TK--------_>>>>>>tank call ok!!!
- TK--------_>>>>>>tankai call ok!!
- */
./test4
[plain]
view plain
copy
- TK----->>>lianjie(a,b) is 20
- TK----->>>lianjie(4,5) is 45
- TK--------_>>>>>>tank call ok!!!
- TK--------_>>>>>>tankai call ok!!
test5.c
[cpp]
view plain
copy
- #include <stdio.h>
- #include "common.h"
- long sys_tank(int fd);
- SYSCALL_DEFINE1(tank, int, fd)
- {
- printf("TK--------_>>>>>>call ok!!!>>fd is %d\n",fd);
- return 0;
- }
- int main(){
- sys_tank(3);
- return 0;
- }
- /*
- SYSCALL_DEFINE1(tank,int,fd) = SYSCALL_DEFINEx(1, _tank, int, fd)
- SYSCALL_DEFINEx(1, _tank, int, fd) = __SYSCALL_DEFINEx(1, _tank, int, fd)
- __SYSCALL_DEFINEx(1, _tank, int, fd) = long sys_tank(__SC_DECL1(int,fd))
- long sys_tank(__SC_DECL1(int,fd))
- //__SC_DECL1(int,fd) = int fd
- //#define __SC_DECL1(t1, a1) t1 a1
- //#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
- //#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
- long sys_tank(__SC_DECL1(int,fd)) = long sys_tank(int fd);
- */
- /*result:
- TK--------_>>>>>>call ok!!!>>fd is 3
- */
./test5
[plain]
view plain
copy
- TK--------_>>>>>>call ok!!!>>fd is 3
test6.c
[cpp]
view plain
copy
- #include <stdio.h>
- #include "common.h"
- long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data);
- SYSCALL_DEFINE5(mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data)
- {
- printf("TK--------_>>>>>>call ok!!!>>>dev_name is %s,dir_name is %s,flags is %d\n",dev_name,dir_name,flags);
- return 0;
- }
- int main(){
- sys_mount(".", "/", NULL, 0, NULL);
- return 0;
- }
- /*
- SYSCALL_DEFINE5(mount,char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data) = SYSCALL_DEFINEx(5, _mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data)
- SYSCALL_DEFINEx(5, _mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data) = __SYSCALL_DEFINEx(5, _mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data)
- __SYSCALL_DEFINEx(5, _mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data) = long sys_tank(__SC_DECL5(char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data))
- long sys_tank(__SC_DECL1(int,fd))
- //__SC_DECL5(char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data) = char * dev_name, __SC_DECL4(char *, dir_name, char *, type, unsigned long, flags, void *, data)
- //......
- //__SC_DECL5(char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data) = char *dev_name, char *dir_name, char *type, unsigned long flags, void *data
- //#define __SC_DECL1(t1, a1) t1 a1
- //#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
- //#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
- //#define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)
- //#define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)
- long sys_mount(__SC_DECL5(int,fd)) = long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data);
- */
- /*result:
- //TK--------_>>>>>>call ok!!!>>>dev_name is .,dir_name is /,flags is 0
- */
./test6
[plain]
view plain
copy
- TK--------_>>>>>>call ok!!!>>>dev_name is .,dir_name is /,flags is 0