日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

ios内联函数 inline

發布時間:2023/12/29 综合教程 22 生活家
生活随笔 收集整理的這篇文章主要介紹了 ios内联函数 inline 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ios內聯函數 inline

緣由

由于在學習使用UIScrollVew開發的過程中,碰到下面這個屬性(設置內邊距):

@property(nonatomic)         UIEdgeInsets                 scrollIndicatorInsets;          // default is UIEdgeInsetsZero. adjust indicators inside 

1

光看UIEdgeInsets這個類型,一時還不知道它的具體內部結構是怎么樣的,于是繼續點進去發現它的定義如下:

typedef struct UIEdgeInsets {
    CGFloat top, left, bottom, right;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;

1
2
3

原來是這樣一個結構體!~ 隨之,看到和UIEdgeInsets相關的使用方法,列舉部分:

UIKIT_STATIC_INLINE UIEdgeInsets UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) {
    UIEdgeInsets insets = {top, left, bottom, right};
    return insets;
}

UIKIT_STATIC_INLINE UIOffset UIOffsetMake(CGFloat horizontal, CGFloat vertical) {
    UIOffset offset = {horizontal, vertical};
    return offset;
}
...

1
2
3
4
5
6
7
8
9
10

看著上面的代碼,又出現了一個我不認識的東西UIKIT_STATIC_INLINE,繼續點進去查看發現這是這么一個宏:

#define UIKIT_STATIC_INLINE static inline

1

哦,原來它的意思是告訴編譯器這個函數是一個靜態的內聯函數!內聯函數?好耳熟啊,但是想不起來具體有什么作用了,于是百度百度!!得出的能令我印象深刻的結論是:

引入內聯函數是為了解決函數調用效率的問題

由于函數之間的調用,會從一個內存地址調到另外一個內存地址,當函數調用完畢之后還會返回原來函數執行的地址。函數調用會有一定的時間開銷,引入內聯函數就是為了解決這一問題。

實踐

那么引用內聯函數到底有什么區別呢?萬一面試問到了,那只能回答”為了解決函數調用效率的問題”?如果面試官再問“如何解決呢?”,那豈不是歇菜了!!不如自己寫代碼測試看看?!!打開xcode..

代碼一

說明:定義一個add(int,int)函數并聲明為static inline,并調用。

頭文件:inline.h

//  inline.h
//  inline
//  Created by fenglh on 15/8/24.
//  Copyright (c) 2015年 fenglh. All rights reserved.

#ifndef inline_inline_h
#define inline_inline_h

static inline int add(int a, int b){
    return a+b;
}
#endif

1
2
3
4
5
6
7
8
9
10
11
12

.m文件:main.m

//  main.m
//  inline
//  Created by fenglj on 15/8/24.
//  Copyright (c) 2015年 fenglh. All rights reserved.

#import <Foundation/Foundation.h>
#import "inline.h"

int main(int argc, const char * argv[]) {
    int c = add(1, 2);
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12

查看main.m的匯編文件,如下:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
Lfunc_begin0:
    .loc    2 14 0                  ## /Users/fenglihai/Desktop/inline/inline/main.m:14:0
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp0:
    .cfi_def_cfa_offset 16
Ltmp1:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp2:
    .cfi_def_cfa_register %rbp
    ##DEBUG_VALUE: main:argc <- EDI
    ##DEBUG_VALUE: main:argv <- RSI
Ltmp3:
    ##DEBUG_VALUE: main:c <- 3
    xorl    %eax, %eax
    .loc    2 17 5 prologue_end     ## /Users/fenglihai/Desktop/inline/inline/main.m:17:5
Ltmp4:
    popq    %rbp
    retq

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

代碼二

說明:定義一個add(int,int)函數并調用。

頭文件:Header.h

//  Header.h
//  notInline
//  Created by fenglh on 15/8/25.
//  Copyright (c) 2015年 fenglh. All rights reserved.

#ifndef notInline_Header_h
#define notInline_Header_h

 int add(int a, int b){
    return a+b;
}

#endif

1
2
3
4
5
6
7
8
9
10
11
12
13

.m文件:main.m

//  main.m
//  notInline
//  Created by fenglh on 15/8/25.
//  Copyright (c) 2015年 fenglh. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Header.h"

int main(int argc, const char * argv[]) {
    int c = add(1,2);
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13

查看main.m的匯編文件,如下:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _add
    .align  4, 0x90
_add:                                   ## @add
Lfunc_begin0:
    .file   3 "/Users/fenglihai/Desktop/notInline/notInline" "Header.h"
    .loc    3 12 0                  ## /Users/fenglihai/Desktop/notInline/notInline/Header.h:12:0
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp0:
    .cfi_def_cfa_offset 16
Ltmp1:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp2:
    .cfi_def_cfa_register %rbp
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    .loc    3 13 5 prologue_end     ## /Users/fenglihai/Desktop/notInline/notInline/Header.h:13:5
Ltmp3:
    movl    -4(%rbp), %esi
    addl    -8(%rbp), %esi
    movl    %esi, %eax
    popq    %rbp
    retq
Ltmp4:
Lfunc_end0:
    .cfi_endproc

    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
Lfunc_begin1:
    .loc    2 12 0                  ## /Users/fenglihai/Desktop/notInline/notInline/main.m:12:0
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp5:
    .cfi_def_cfa_offset 16
Ltmp6:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp7:
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    movl    $1, %eax
    movl    $2, %ecx
    movl    $0, -4(%rbp)
    movl    %edi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    .loc    2 13 13 prologue_end    ## /Users/fenglihai/Desktop/notInline/notInline/main.m:13:13
Ltmp8:
    movl    %eax, %edi
    movl    %ecx, %esi
    callq   _add
    xorl    %ecx, %ecx
    movl    %eax, -20(%rbp)
    .loc    2 14 5                  ## /Users/fenglihai/Desktop/notInline/notInline/main.m:14:5
    movl    %ecx, %eax
    addq    $32, %rsp
    popq    %rbp
    retq

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


上面2段代碼可以看出,只有add函數的定義不一樣,一個是加了static inline修飾,而另外一個沒有。再對比一下匯編代碼,發現的確有很大的不一樣呀!!!給人第一感覺,有用static inline修飾的匯編之后的代碼比沒有static inline修飾的的匯編之后的代碼簡潔的多了!!

其次,在沒有調用static inline修飾add函數的main.m匯編代碼中,add函數是有單獨的匯編代碼的!

而沒有使用內聯函數的main.m匯編代碼中,僅僅只有main函數的匯編代碼!

再看看使用了內聯函數的main.m匯編代碼:

對比兩者的mian.m的匯編代碼,可以發現,沒有使用`static inline修飾的內聯函數的mian函數匯編代碼中,會出現 call 指令!這就是區別!調用call指令就是就需要:
-(1)將下一條指令的所在地址(即當時程序計數器PC的內容)入棧
-(2)并將子程序的起始地址送入PC(于是CPU的下一條指令就會轉去執行子程序)。

恩恩,對于匯編就不扯淡了,憑借著上學時候學過點匯編只能深入到這里了!唉!那么得知,影響效率的原因就是在解決在call調用這里了!!

結論

1.使用inline修飾的函數,在編譯的時候,會把代碼直接嵌入調用代碼中。就相當于用#define 宏定義來定義一個add 函數那樣!與#define的區別是:
1)#define定義的格式要有要求,而使用inline則就行平常寫函數那樣,只要加上`inline即可!
2)使用#define宏定義的代碼,編譯器不會對其進行參數有效性檢查,僅僅只是對符號表進行替換。
3)#define宏定義的代碼,其返回值不能被強制轉換成可轉換的適合的轉換類型。可參考百度文科關于inline

2.在inline加上`static修飾符,只是為了表明該函數只在該文件中可見!也就是說,在同一個工程中,就算在其他文件中也出現同名、同參數的函數也不會引起函數重復定義的錯誤!**

實踐到這里,對于內聯函數終的理解,終于加深理解和記憶了!!

總結

以上是生活随笔為你收集整理的ios内联函数 inline的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。