Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2089464
  • 博文数量: 361
  • 博客积分: 10828
  • 博客等级: 上将
  • 技术积分: 4161
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-20 14:34
文章分类

全部博文(361)

文章存档

2011年(132)

2010年(229)

分类: C/C++

2010-04-23 14:20:39

1.
#define Conn(x,y) x##y

x##y表示x连接y,举例说明:
int n = Conn(123,456); 结果就是n = 123456;
char* str = Conn("abc","def"); 结果就是 str = "abcdef";

2.
#define ToChar(x)
,就是给x加上单引号,结果返回一个 const char,举例说明:
char a = ToChar(1); 结果就是 a = '1';
做个越界试验 char a = ToChar(123); 结果是 a = '3';
但是如果参数超过四个字符,编译器就会报错。

3.
#define ToString(x) #x

#x就是给x加上双引号,举例说明:
char* str = ToString(1234); 结果是 str = "1234";

 

 理解系统调用:


(一)

#define _syscall0(type,name)                        \
type name(void) {                            \
  register long __res_r0 __asm__("r0");                    \
  long __res;                                \
  __asm__ __volatile__ (                        \
  __syscall(name)                            \
    : "=r" (__res_r0)                        \
    :                                \
    : "lr");                            \
  __res = __res_r0;                            \
  __syscall_return(type,__res);                        \
}

(二)

#define __syscall(name) "swi\t" __sys1(__NR_##name) ""

#define __sys1(x) __sys2(x)

#define __sys2(x) #x

(三)

#define __NR_fork            (__NR_SYSCALL_BASE+  2)

#define __NR_SYSCALL_BASE    0x900000


那么 _syscall0(int, fork)中 __syscall(name) 替换后为:

(1) 替换name======>“swi\t" __sys1(__NR_##fork) ""

(2) ##为连接的意思,故为=========> "swi\t " __sys1(__NR_fork) ""

(3)替换__NR_fork,故为==========> "swi\t " __sys1(0x900002) ""

(4)替换__sys1(x),故为============> "swi\t " __sys2(0x900002) ""

(5)#为给x加双引号,故为==========> "swi\t "0x900002" ""

(6)故最后变成:"swi\t 0x900002 "

其意思即为fork的系统调用,最后变成了一个软中断调用,地址为0x900002

===================================================================================================

常规用法不再介绍,做如下几点说明和介绍

1. 带参数的宏只完成简单字符替换,之前不做计算实参的工作,如下

 

#define SUM(x,y) x+y

int a=3,b=2,c=1;
int s;
s
=SUM(a+b,b)*SUM(c,b)+c;

 

            结果应该是 s=a+b+b*c+b+c=10。

2. define中的特殊标识符

#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x

int a=Conn(12,34);
char b=ToChar(a);
char c[]=ToString(a);

结果是 a=1234,c='a',c='1234';

可以看出 ## 是简单的连接符,#@用来给参数加单引号,#用来给参数加双引号即转成字符串。

更神奇的是

#define x(s) #s
   char *= x(a   b/**/ c);
char *= x(anb);

结果是*s='a  b  c',*p='a\nb',#s果然很厉害

3.define的多行定义

define可以替代多行的代码

#define MACRO(arg1, arg2) do {\
stmt1;\
stmt2; \
while(0

关键是要在每一个换行的时候加上一个'\' 

由此联想到了C中的关于字符串的一些默认规则

char s1[]='abc'  'efg';
char s2[]='abc'
'efg';
char s3[]='ab
c';
char s4[]='ab
c';

其中只有s4会产生编译错误,s1='abcefg',s2='abcefg',s3='abc'

4. 宏调用顺序

#define A 3
#define B 4
#define AB 5
#define Conn(x,y) x##y

int a=Conn(A,B);

结果是a=5;可见一个宏的参数是另一个宏,先替换外面的宏,后替换参数。即Conn(A,B)=>AB,后AB=>5

 5.解决重复定义的问题
由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__

文件内容

#endif

阅读(877) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~