2017年9月8日 星期五

C語言中 ,inline的用法

基本上在C語言中,inline語法會有三種情況(inline、static inline、extern inline)。

但由於inline跟extern inline的用法在GCC跟C99中幾乎相反,為了相容性,必需得有一種通用的寫法(下面會提到)。而static inline就沒有什麼問題。

已經有人把所有的差異點寫的很清楚了https://read01.com/zh-tw/3APOEG.html#.WbEKVNDTSUk,所以直接下結論。

註:inline只是建議編譯器要做行內編譯,實際上編譯器不一定會執行。通常要 -O1 以上才有效果。

static inline:

  • 因為有static,所以很好理解,就是只在單一文件可見。如果要大家都可以共用,就只能放在h檔中了。這也是最通用的做法。
  • 效果就是除非無法做行內編譯(例如:遞迴函式或是會用這個函式的指標),不然就不會產生獨立的程式碼。
  • 實驗用程式:
  1. #include <stdio.h>
  2. static inline void ttt() {
  3. return;
  4. }
  5. int main()
  6. {
  7. ttt();
  8. return 0;
  9. }
  •  用objdump看一下,會發現只有main,ttt這個函式不會產生獨立的程式碼。
00000000004004b0 <frame_dummy>:
  4004b0: bf 20 0e 60 00       mov    $0x600e20,%edi
  4004b5: 48 83 3f 00           cmpq   $0x0,(%rdi)
  4004b9: 75 05                 jne    4004c0 <frame_dummy+0x10>
  4004bb: eb 93                 jmp    400450 <register_tm_clones>
  4004bd: 0f 1f 00             nopl   (%rax)
  4004c0: b8 00 00 00 00       mov    $0x0,%eax
  4004c5: 48 85 c0             test   %rax,%rax
  4004c8: 74 f1                 je     4004bb <frame_dummy+0xb>
  4004ca: 55                   push   %rbp
  4004cb: 48 89 e5             mov    %rsp,%rbp
  4004ce: ff d0                 callq  *%rax
  4004d0: 5d                   pop    %rbp
  4004d1: e9 7a ff ff ff       jmpq   400450 <register_tm_clones>
00000000004004d6 <main>:
  4004d6: b8 00 00 00 00       mov    $0x0,%eax
  4004db: c3                   retq
  4004dc: 0f 1f 40 00           nopl   0x0(%rax)
00000000004004e0 <__libc_csu_init>:
  4004e0: 41 57                 push   %r15
  4004e2: 41 56                 push   %r14

inline & extern inline
  • 由於效果在GCC跟C99中幾乎相反,推薦以下寫法,編譯的結果才不會不一致。
  • 效果會是:函式所在的C檔中,會執行行內編譯。其他C檔中,會被視為一般的函式,所以為了讓其他的C檔連結到,一定會產生獨立的程式碼。
  • 實驗用程式(推薦的寫法),需要留意的是,extern後面不可以加inline:
  1. #include <stdio.h>
  2. extern void ttt(void);
  3. inline void ttt() {
  4. return;
  5. }
  6. int main()
  7. {
  8. ttt();
  9. return 0;
  10. }
  • 用objdump看一下,會發現ttt這個函式會產生獨立的程式碼,但是main仍然是以行內編譯的方式編譯ttt()。
  4004ce: ff d0                 callq  *%rax
  4004d0: 5d                   pop    %rbp
  4004d1: e9 7a ff ff ff       jmpq   400450 <register_tm_clones>
00000000004004d6 <ttt>:
  4004d6: f3 c3                 repz retq
00000000004004d8 <main>:
  4004d8: b8 00 00 00 00       mov    $0x0,%eax
  4004dd: c3                   retq  
  4004de: 66 90                 xchg   %ax,%ax
00000000004004e0 <__libc_csu_init>:
  4004e0: 41 57                 push   %r15
  4004e2: 41 56                 push   %r14

沒有留言:

張貼留言