《C预处理》Linux内核中可变参数宏的用法

C语言预处理包括:宏定义、文件包含、条件编译等;预处理命令都以#开头:宏(#define)、文件包含(#include)、条件编译(#ifdef或#ifndef)。

本节主要分析宏定义的特殊用法。

一、#与##

1.#

#符号用作一个预处理运算符,它可以把语言符号转换成字符串。

eg:x是一个宏参数,那么#x可以把参数名转换成相应的字符串,这个过程叫字符串化。

test1.c

  1. #include <stdio.h>  
  2. #define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))  
  3. int main(void)  
  4. {  
  5.     int y =4;  
  6.     PSQR(y);  
  7.     PSQR(2+4);  
  8.     return 0;  
  9. }  
  10.   
  11. /*result: 
  12. the square ofyis 16. 
  13. the square of2+4is 36. 
  14. */  
gcc test1.c -o test1

./test1

[plain] view plain copy
  1. the square ofyis 16.  
  2. the square of2+4is 36.  
2.##

该运算符把两个语言符号组合成单个语言符号。

test2.c

  1. #include <stdio.h>  
  2. #define XNAME(n) x##n  
  3. #define PXN(n) printf("x"#n" = %d\n",x##n)  
  4. int main(void)  
  5. {  
  6.     int XNAME(1)=12;//int x1=12;  
  7.     PXN(1);//printf("x1 = %d\n", x1);  
  8.     return 0;  
  9. }  
  10.   
  11. /*result: 
  12. x1 = 12 
  13. */  
gcc test2.c -o test2

./test2

[plain] view plain copy
  1. x1 = 12  
二、可变参数宏与__VA_ARGS__

__VA_ARGS__是一个可变参数宏,是新的C99规范中新增的,目前只有gcc支持(VC6.0的编译器不支持)。

宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所代表的字符串。

简单例子:

test3.c

  1. #include <stdio.h>  
  2. #define PR(...) printf(__VA_ARGS__)  
  3. int main()  
  4. {  
  5.     int wt=1,sp=2;  
  6.     PR("hello\n");  
  7.     PR("weight = %d, shipping = %d\n",wt,sp);  
  8.     return 0;  
  9. }  
  10. /*result: 
  11. hello 
  12. weight = 1, shipping = 2 
  13. */  
gcc test3.c -o test3

./test3

[plain] view plain copy
  1. hello  
  2. weight = 1, shipping = 2  
三、在Linux内核系统调用中的应用

公共接口:

common.h(相当与内核中的systemcalls.h)

  1. #define __SC_DECL1(t1, a1)    t1 a1  
  2. #define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)  
  3. #define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)  
  4. #define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)  
  5. #define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)  
  6. #define __SYSCALL_DEFINEx(x, name, ...)                 \  
  7.      long sys##name(__SC_DECL##x(__VA_ARGS__))  
  8. #define SYSCALL_DEFINEx(x, sname, ...)              \  
  9.     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)  
  10. #define SYSCALL_DEFINE0(name)      long sys_##name(void)  
  11. #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)  
  12. #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)  
1.无参数

test4.c

  1. #include <stdio.h>  
  2. #include "common.h"  
  3.   
  4. long sys_tank(void);  
  5. long sys_tankai(void);  
  6.   
  7. SYSCALL_DEFINE0(tank)  
  8. {  
  9.   printf("TK--------_>>>>>>tank call ok!!!\n");  
  10. }  
  11.   
  12. SYSCALL_DEFINE0(tankai)  
  13. {  
  14.   printf("TK--------_>>>>>>tankai call ok!!!\n");  
  15. }  
  16.   
  17. int main(){  
  18.   sys_tank();  
  19.   sys_tankai();  
  20.   return 0;  
  21. }  
  22.   
  23. /*result: 
  24. TK----->>>lianjie(a,b) is 20 
  25. TK----->>>lianjie(4,5) is 45 
  26. TK--------_>>>>>>tank call ok!!! 
  27. TK--------_>>>>>>tankai call ok!! 
  28. */  
gcc test4.c -o test4

./test4

[plain] view plain copy
  1. TK----->>>lianjie(a,b) is 20  
  2. TK----->>>lianjie(4,5) is 45  
  3. TK--------_>>>>>>tank call ok!!!  
  4. TK--------_>>>>>>tankai call ok!!  
2.一个参数

test5.c

  1. #include <stdio.h>  
  2. #include "common.h"  
  3.   
  4.   
  5. long sys_tank(int fd);  
  6.   
  7. SYSCALL_DEFINE1(tank, int, fd)  
  8. {  
  9.   printf("TK--------_>>>>>>call ok!!!>>fd is %d\n",fd);  
  10.   return 0;  
  11. }  
  12.   
  13. int main(){  
  14.   sys_tank(3);  
  15.   return 0;  
  16. }  
  17.   
  18.   
  19. /* 
  20. SYSCALL_DEFINE1(tank,int,fd) = SYSCALL_DEFINEx(1, _tank, int, fd) 
  21. SYSCALL_DEFINEx(1, _tank, int, fd) = __SYSCALL_DEFINEx(1, _tank, int, fd) 
  22. __SYSCALL_DEFINEx(1, _tank, int, fd) = long sys_tank(__SC_DECL1(int,fd)) 
  23. long sys_tank(__SC_DECL1(int,fd)) 
  24. //__SC_DECL1(int,fd) = int fd 
  25. //#define __SC_DECL1(t1, a1)    t1 a1 
  26. //#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__) 
  27. //#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__) 
  28. long sys_tank(__SC_DECL1(int,fd)) = long sys_tank(int fd); 
  29. */  
  30.   
  31. /*result: 
  32. TK--------_>>>>>>call ok!!!>>fd is 3 
  33. */  
gcc test5.c -o test5

./test5

[plain] view plain copy
  1. TK--------_>>>>>>call ok!!!>>fd is 3  
3.五个参数情况,其他不再罗列

test6.c

  1. #include <stdio.h>  
  2. #include "common.h"  
  3.   
  4. long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data);  
  5.   
  6. SYSCALL_DEFINE5(mount, char *, dev_name, char *, dir_name, char *, type, unsigned long, flags, void *, data)  
  7. {  
  8.   printf("TK--------_>>>>>>call ok!!!>>>dev_name is %s,dir_name is %s,flags is %d\n",dev_name,dir_name,flags);  
  9.   return 0;  
  10. }  
  11.   
  12. int main(){  
  13.   sys_mount(".", "/", NULL, 0, NULL);  
  14.   return 0;  
  15. }  
  16.   
  17.   
  18. /* 
  19. 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) 
  20. 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) 
  21. __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)) 
  22. long sys_tank(__SC_DECL1(int,fd)) 
  23. //__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) 
  24. //...... 
  25. //__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 
  26. //#define __SC_DECL1(t1, a1)    t1 a1 
  27. //#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__) 
  28. //#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__) 
  29. //#define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__) 
  30. //#define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__) 
  31. long sys_mount(__SC_DECL5(int,fd)) = long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data); 
  32. */  
  33.   
  34.   
  35. /*result: 
  36. //TK--------_>>>>>>call ok!!!>>>dev_name is .,dir_name is /,flags is 0 
  37. */  
gcc test6.c -o test6

./test6

[plain] view plain copy
  1. TK--------_>>>>>>call ok!!!>>>dev_name is .,dir_name is /,flags is 0 



转载于:https://my.oschina.net/u/1024767/blog/324735

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值