欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

内联函数与宏替换的区别

程序员文章站 2024-03-23 14:21:04
...
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去替换,而不是用复杂的表达式替换)