小南地带 2019-06-29
C++ 中的 const 常量可以替代宏常数定义
const int A; <==> #define A 3C++ 中是否有解决方案替代宏代码片段呢?
inline int func(int a, int b)
{
return a < b ? a : b;
}内联函数声明时 inline 关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
C++ 编译器不一定满足函数的内联请求!
#include <stdio.h>
#define FUNC(a, b) ((a) < (b) ? (a) : (b))
inline int func(int a, int b)
{
return a < b ? a : b;
}
void code_1()
{
int a = 1;
int b = 3;
int c = FUNC(++a, b);
printf("\ncode_1: \n");
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
}
void code_2()
{
int a = 1;
int b = 3;
int c = func(++a, b);
printf("\ncode_2: \n");
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
}
int main(int arc, char* argv[])
{
code_1();
code_2();
return 0;
}输出: code_1: a = 3 b = 3 c = 3 code_2: a = 2 b = 3 c = 2 分析: 【宏无法避免的副作用】 int c = FUNC(++a, b); ==> int = ((++a) < (b) ? (++a) : (b))
宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用。
一些现代 C++ 编译器提供了扩展语法,能够对函数进行强制内联(这降低了可移植行)
#include <stdio.h>
// __forceinline
// __attribute__((always_inline))
inline
int add_inline(int n);
int main(int argc, char* argv[])
{
int r = add_inline(10);
printf("r = %d\n", r);
return 0;
}
inline int add_inline(int n)
{
int ret = 0;
for(int i=0; i<n; i++)
{
ret += i;
}
return n;
}内联函数扩展选项默认,未强制内联时
VC2010 汇编:【内联请求失败】
int r = add_inline(10); 010E13AE push 0Ah 010E13B0 call add_inline (10E104Bh) ; 发生函数调用 010E13B5 add esp,4 010E13B8 mov dword ptr [r],eax
g++ 汇编 【内联请求失败】
main(int, char**): 08048494: push %ebp 08048495: mov %esp,%ebp 08048497: and $0xfffffff0,%esp 0804849a: sub $0x20,%esp 0804849d: movl $0xa,(%esp) 080484a4: call 0x80484c8 <add_inline(int)> ; 发生函数调用 080484a9: mov %eax,0x1c(%esp) 080484ad: mov 0x1c(%esp),%eax 080484b1: mov %eax,0x4(%esp) 080484b5: movl $0x80485c0,(%esp) 080484bc: call 0x80483c0 <printf@plt> 080484c1: mov $0x0,%eax 080484c6: leave 080484c7: ret
内联函数扩展选项默认,强制内联时
VC2010 汇编:【内联请求成功】
int r = add_inline(10); 008C102C mov dword ptr [ebp-8],0 008C1033 mov dword ptr [ebp-0Ch],0 008C103A jmp wmain+35h (8C1045h) 008C103C mov eax,dword ptr [ebp-0Ch] 008C103F add eax,1 008C1042 mov dword ptr [ebp-0Ch],eax 008C1045 cmp dword ptr [ebp-0Ch],0Ah 008C1049 jge wmain+46h (8C1056h) 008C104B mov ecx,dword ptr [ebp-8] 008C104E add ecx,dword ptr [ebp-0Ch] 008C1051 mov dword ptr [ebp-8],ecx 008C1054 jmp wmain+2Ch (8C103Ch) 008C1056 mov edx,dword ptr [ebp-8] 008C1059 mov dword ptr [r],edx
g++ 汇编 【内联请求成功】
main(int, char**):
08048494: push %ebp
08048495: mov %esp,%ebp
08048497: and $0xfffffff0,%esp
0804849a: sub $0x20,%esp
9 {
0804849d: movl $0xa,0x18(%esp)
19 int ret = 0;
080484a5: movl $0x0,0x14(%esp)
21 for(int i=0; i<n; i++)
080484ad: movl $0x0,0x10(%esp)
080484b5: jmp 0x80484c4 <main(int, char**)+48>
23 ret += i;
080484b7: mov 0x10(%esp),%eax
080484bb: add %eax,0x14(%esp)
21 for(int i=0; i<n; i++)
080484bf: addl $0x1,0x10(%esp)
080484c4: mov 0x18(%esp),%eax
080484c8: cmp 0x10(%esp),%eax
080484cc: setg %al
080484cf: test %al,%al
080484d1: jne 0x80484b7 <main(int, char**)+35>
26 return ret;
080484d3: mov 0x14(%esp),%eax
10 int r = add_inline(10);
080484d7: mov %eax,0x1c(%esp)
12 printf(" r = %d\n", r);
080484db: mov 0x1c(%esp),%eax
080484df: mov %eax,0x4(%esp)
080484e3: movl $0x80485c0,(%esp)
080484ea: call 0x80483c0 <printf@plt>
14 return 0;
080484ef: mov $0x0,%eax
15 }C++ 中 inline 内联编译的限制(现在编译器基本都可满足内联要求,以下针对旧编译器而言)
以上内容参考狄泰软件学院系列课程,请大家保护原创!