天天看点

内联函数与宏替换的区别

1)内联函数在运行时可调试,而宏不可以

2)内联函数可以访问类的成员变量,而宏不可以

3)在类中声明同时定义的简单的函数,会自动转换为内联函数

4)编译器会对内联函数的参数类型做安全检查

:内联函数具有宏的替换效果,以及普通函数的安全检查

#define max(a,b) ((a) > (b) ?(a) :(b))    //一定要带括号,优先级不同会造成意想不到的结果

int a=1,b=0;

max(a++,b);    ->    {a++ > b ? a++ : b}    ->    

等价:

if(a++ > b)

  return a++;

else

  return b;

最后:

max=2;

a=3;

max(a++,b+10);    ->    {a++ > b+10 ? a++ : b+10}    ->

等价:

if(a++ > b+10)

  return a++;

else

  return b+10;

最后:

b的值一直不变,最后加10等于10;

max(a,"hello");    -> 编译不通过

#define f(x)  (x+x)

int x=1;

f(x++);

等价:

(x++) + (x++) -> return x+x=2

x=3

f(++x);

等价:

(++x) + (++x) -> return 3+3=6

x=3

int x=5;

( (x++) + (++x) + (++x) ) = 21;

x=8;

【问题】:C语言宏定义#define max(a,b) a>b?a:b 有什么隐患?

因为宏定义是在预编译阶段把宏的内容拷贝的源代码的相应位置

如果#define max(a,b) a>b?a:b这样写的话

那么如下表达式 max(a,b)+1就展开为

a>b?a:b+1

冒号后面就是b+1了,自然和lz的当初愿望,算完max再加一违背了

所以要加上括号。

内联函数中如果复杂操作,将不被内联,如循环,递归。

inline应该放在函数定义处,不要放在声明前.

inline  是用以实现的关键字,

    不是用以声明的关键字.

总结:宏替换有很多意想不到的错误,当要实现的东西较为复杂时,建议使用函数。

知识扩展:

int main()

{

    int result = __extension__({

    int i, sum = 0;

     for (i = 1; i <= 100; i++)

          sum+= i;

     sum;

    })

    printf("result=%d\n", result);

}
           

({statement list})是一个表达式,逗号表达式类似,但是功能更强,({与})中可以包含有多条语句(可以是变量定义、复杂的控制语句),该表达式的值为statement list中最后一条语句的值

typeof(expression)用来获取expression的类型

gcc选项-ansi指示编译器编译符合标准的程序,但是不限制其它方式,只要它与标准不冲突。这样,asm、typeof、inline都将无效,但是__asm__、__typeof__、__inline__还将有效。

经常与-ansi一起使用的是-pedantic选项,它严格按照ISO标准产生需要的警告信息,但是如果程序中使用了__extension__,则-pedantic选项对__extension__后的表达式无影响。

如果要非常严格,可以使用-pedantic-errors选项。这样,所有与标准不符和的代码统统被编译器当成是错误而不是警告。

所以:

#define min(X,Y) \

({  \

typeof(X) __x=(X), __y=(Y);  \

(__x<__y)?__x:__y;  \

})      

这样宏定义,就不会出现x++,这种被执行多次的情况了.(这里是用新的变量_x去替换,而不是用复杂的表达式替换)

c++

继续阅读