内联函数与宏替换的区别
程序员文章站
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 是用以实现的关键字,
不是用以声明的关键字.
总结:宏替换有很多意想不到的错误,当要实现的东西较为复杂时,建议使用函数。
({statement list})是一个表达式,逗号表达式类似,但是功能更强,({与})中可以包含有多条语句(可以是变量定义、复杂的控制语句),该表达式的值为statement list中最后一条语句的值
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去替换,而不是用复杂的表达式替换)
上一篇: JDK8新特性