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

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

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

一、#与##

1.#

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

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

test1.c

#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.
*/
gcc test1.c -o test1

./test1

the square ofyis 16.
the square of2+4is 36.
2.##

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

test2.c

#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
*/
gcc test2.c -o test2

./test2

x1 = 12
二、可变参数宏与__VA_ARGS__

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

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

简单例子:

test3.c

#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
*/
gcc test3.c -o test3

./test3

hello
weight = 1, shipping = 2
三、在Linux内核系统调用中的应用

公共接口:

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

#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__)
1.无参数

test4.c

#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!!
*/
gcc test4.c -o test4

./test4

TK----->>>lianjie(a,b) is 20
TK----->>>lianjie(4,5) is 45
TK--------_>>>>>>tank call ok!!!
TK--------_>>>>>>tankai call ok!!
2.一个参数

test5.c

#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
*/
gcc test5.c -o test5

./test5

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

test6.c

#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
*/
gcc test6.c -o test6

./test6

TK--------_>>>>>>call ok!!!>>>dev_name is .,dir_name is /,flags is 0


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值