普通函数和内联函数

本篇文章主要验证普通函数和内联函数的区别

Inline_function.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
__attribute__((always_inline))
inline void func() {
int j = 0;
for (int i = 0; i < 2; i++) {
j++;
if (j == 20) j *= 2;
}
}

int main() {
func();
func();
func();
func();
func();
return 0;
}

__attribute__((always_inline))告诉编译器强制内联。

outline_function.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void func() __attribute__((noinline));
void func() {
int j = 0;
for (int i = 0; i < 2; i++) {
j++;
if (j == 20) j *= 2;
}
}

int main() {
func();
func();
func();
func();
func();
return 0;
}

__attribute__((noinline))告诉编译器一定不要内联

让我们分别编译下并反汇编一下可执行文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
$ g++ -O0 inline_function.cpp -o inline_out_file.app
$ g++ -O0 outline_function.cpp -o outline_out_file.app
$ objdump -d inline_out_file.app | less
0000000100003e50 <_main>:
100003e50: 55 pushq %rbp
100003e51: 48 89 e5 movq %rsp, %rbp
100003e54: c7 45 d4 00 00 00 00 movl $0, -44(%rbp)
100003e5b: c7 45 dc 00 00 00 00 movl $0, -36(%rbp)
100003e62: c7 45 d8 00 00 00 00 movl $0, -40(%rbp)
100003e69: 83 7d d8 02 cmpl $2, -40(%rbp)
100003e6d: 0f 8d 2a 00 00 00 jge 0x100003e9d <_main+0x4d>
100003e73: 8b 45 dc movl -36(%rbp), %eax
100003e76: 83 c0 01 addl $1, %eax
100003e79: 89 45 dc movl %eax, -36(%rbp)
100003e7c: 83 7d dc 14 cmpl $20, -36(%rbp)
100003e80: 0f 85 09 00 00 00 jne 0x100003e8f <_main+0x3f>
100003e86: 8b 45 dc movl -36(%rbp), %eax
100003e89: c1 e0 01 shll $1, %eax
100003e8c: 89 45 dc movl %eax, -36(%rbp)
100003e8f: 8b 45 d8 movl -40(%rbp), %eax
100003e92: 83 c0 01 addl $1, %eax
100003e95: 89 45 d8 movl %eax, -40(%rbp)
100003e98: e9 cc ff ff ff jmp 0x100003e69 <_main+0x19>
100003e9d: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003ea4: c7 45 f8 00 00 00 00 movl $0, -8(%rbp)
100003eab: 83 7d f8 02 cmpl $2, -8(%rbp)
100003eaf: 0f 8d 2a 00 00 00 jge 0x100003edf <_main+0x8f>
100003eb5: 8b 45 fc movl -4(%rbp), %eax
100003eb8: 83 c0 01 addl $1, %eax
100003ebb: 89 45 fc movl %eax, -4(%rbp)
100003ebe: 83 7d fc 14 cmpl $20, -4(%rbp)
100003ec2: 0f 85 09 00 00 00 jne 0x100003ed1 <_main+0x81>
100003ec8: 8b 45 fc movl -4(%rbp), %eax
100003ecb: c1 e0 01 shll $1, %eax
100003ece: 89 45 fc movl %eax, -4(%rbp)
100003ed1: 8b 45 f8 movl -8(%rbp), %eax
100003ed4: 83 c0 01 addl $1, %eax
100003ed7: 89 45 f8 movl %eax, -8(%rbp)
100003eda: e9 cc ff ff ff jmp 0x100003eab <_main+0x5b>
100003edf: c7 45 f4 00 00 00 00 movl $0, -12(%rbp)
100003ee6: c7 45 f0 00 00 00 00 movl $0, -16(%rbp)
100003eed: 83 7d f0 02 cmpl $2, -16(%rbp)
100003ef1: 0f 8d 2a 00 00 00 jge 0x100003f21 <_main+0xd1>
100003ef7: 8b 45 f4 movl -12(%rbp), %eax
100003efa: 83 c0 01 addl $1, %eax
100003efd: 89 45 f4 movl %eax, -12(%rbp)
100003f00: 83 7d f4 14 cmpl $20, -12(%rbp)
100003f04: 0f 85 09 00 00 00 jne 0x100003f13 <_main+0xc3>
100003f0a: 8b 45 f4 movl -12(%rbp), %eax
100003f0d: c1 e0 01 shll $1, %eax
100003f10: 89 45 f4 movl %eax, -12(%rbp)
100003f13: 8b 45 f0 movl -16(%rbp), %eax
100003f16: 83 c0 01 addl $1, %eax
100003f19: 89 45 f0 movl %eax, -16(%rbp)
100003f1c: e9 cc ff ff ff jmp 0x100003eed <_main+0x9d>
100003f21: c7 45 ec 00 00 00 00 movl $0, -20(%rbp)
100003f28: c7 45 e8 00 00 00 00 movl $0, -24(%rbp)
100003f2f: 83 7d e8 02 cmpl $2, -24(%rbp)
100003f33: 0f 8d 2a 00 00 00 jge 0x100003f63 <_main+0x113>
100003f39: 8b 45 ec movl -20(%rbp), %eax
100003f3c: 83 c0 01 addl $1, %eax
100003f3f: 89 45 ec movl %eax, -20(%rbp)
100003f42: 83 7d ec 14 cmpl $20, -20(%rbp)
100003f46: 0f 85 09 00 00 00 jne 0x100003f55 <_main+0x105>
100003f4c: 8b 45 ec movl -20(%rbp), %eax
100003f4f: c1 e0 01 shll $1, %eax
100003f52: 89 45 ec movl %eax, -20(%rbp)
100003f55: 8b 45 e8 movl -24(%rbp), %eax
100003f58: 83 c0 01 addl $1, %eax
100003f5b: 89 45 e8 movl %eax, -24(%rbp)
100003f5e: e9 cc ff ff ff jmp 0x100003f2f <_main+0xdf>
100003f63: c7 45 e4 00 00 00 00 movl $0, -28(%rbp)
100003f6a: c7 45 e0 00 00 00 00 movl $0, -32(%rbp)
100003f71: 83 7d e0 02 cmpl $2, -32(%rbp)
100003f75: 0f 8d 2a 00 00 00 jge 0x100003fa5 <_main+0x155>
100003f7b: 8b 45 e4 movl -28(%rbp), %eax
100003f7e: 83 c0 01 addl $1, %eax
100003f81: 89 45 e4 movl %eax, -28(%rbp)
100003f84: 83 7d e4 14 cmpl $20, -28(%rbp)
100003f88: 0f 85 09 00 00 00 jne 0x100003f97 <_main+0x147>
100003f8e: 8b 45 e4 movl -28(%rbp), %eax
100003f91: c1 e0 01 shll $1, %eax
100003f94: 89 45 e4 movl %eax, -28(%rbp)
100003f97: 8b 45 e0 movl -32(%rbp), %eax
100003f9a: 83 c0 01 addl $1, %eax
100003f9d: 89 45 e0 movl %eax, -32(%rbp)
100003fa0: e9 cc ff ff ff jmp 0x100003f71 <_main+0x121>
100003fa5: 31 c0 xorl %eax, %eax
100003fa7: 5d popq %rbp
100003fa8: c3 retq

$ objdump -d outline_out_file.app | less
0000000100003f80 <_main>:
100003f80: 55 pushq %rbp
100003f81: 48 89 e5 movq %rsp, %rbp
100003f84: 48 83 ec 10 subq $16, %rsp
100003f88: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003f8f: e8 9c ff ff ff callq 0x100003f30 <__Z4funcv>
100003f94: e8 97 ff ff ff callq 0x100003f30 <__Z4funcv>
100003f99: e8 92 ff ff ff callq 0x100003f30 <__Z4funcv>
100003f9e: e8 8d ff ff ff callq 0x100003f30 <__Z4funcv>
100003fa3: e8 88 ff ff ff callq 0x100003f30 <__Z4funcv>
100003fa8: 31 c0 xorl %eax, %eax
100003faa: 48 83 c4 10 addq $16, %rsp
100003fae: 5d popq %rbp
100003faf: c3 retq

可以看出来普通函数都是用call来调用函数,生成的可执行文件比较小。而内联函数则是把函数体复制粘贴,生成的可执行文件比较大