結構體中使用指針

最近在方法抽取時,使用了結構體來來支持自定義數值傳值,本來一切都順順利利,但在處理特定情況,需要在結構體中定義一個傳遞一個指向數組的指針時,出了問題,指針在用時,拿不到值。

結構體中使用指針

初始使用代碼如下

typedef struct {
    int *p;
    int count;
} ZLLAverge;

 ZLLAverge defaultAverge() {
    int a[] = {1, 2, 3};
    ZLLAverge averge;
    averge.count = sizeof(a) / sizeof(int);
    averge.p = a;
    return averge;
}

- (void)test1:(ZLLAverge)averge {
    for (int i = 0; i < averge.count; i++) {
        printf("%i ", averge.p[i]);
         printf("------------\n");
    }
}
- (void)viewDidLoad {
    [super viewDidLoad];
  
    [self test1:defaultAverge()];
  }
//結果如下
0 -1074336348 3 ------------

后面又嘗試了兩種情況

- (ZLLAverge)ctreateAverge{
    int a[] = {4, 5, 6};
    ZLLAverge averge;
    averge.count = sizeof(a) / sizeof(int);
    averge.p = a;

    return averge;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZLLAverge averge = [self ctreateAverge];
    [self test1:averge];
 
    ZLLAverge averge1;
     int a[] = {7, 8, 9};;
    averge1.count = sizeof(a) / sizeof(int);
    averge1.p = a;
    [self test1:averge1];
}
//結果如下
0 -1074639484 3 ------------
7 8 9 ------------

嘗試到這兒,回想起以前學習的東西,串起來就明白了。

每個函數(方法)在執行時會在棧區分配一塊內存空間,在函數內部創建的局部變量就分配在這塊內存空間內,當函數執行完時這塊內存空間會被回收。但結構體是值傳遞,所以不受影響,指針的值還在,而上面的指針指向的內存地址中的數據,在函數返回時已被回收,取出的數據就不是我們想要的了。

正確的使用是使用malloc函數,在堆區開辟一塊內存空間,同時使用memcpy函數將在棧區的指針指向的內存地址中的數據拷貝到堆區,這樣在函數返回時就不會被回收,影響我們的使用了。

 ZLLAverge defaultAverge() {
    int a[] = {1, 2, 3};
    ZLLAverge averge;
    averge.count = sizeof(a) / sizeof(int);
 
    size_t memory_size = averge.count * sizeof(int);
    int *newA = (int *)malloc(memory_size);
    memcpy(newA, a, memory_size);
    averge.p = newA;
    return averge;
}
//
1 2 3 ------------

PS:注意 使用malloc函數開辟的內存空間,要自己釋放,不然會有內存泄露。

優雅的使用

上面我們已經解決了問題,但如果我們的代碼是提供給別人用的呢,如何給提示信息,注意上面提到的問題呢。或者如果要在別的結構體中使用有指針的結構體呢。有很多方法,但怎樣做才簡單而優雅呢,在定義這種類型的結構體時提供創建和銷毀方法,代碼如下:

//再加一些注釋就更完美了
typedef struct {
    int *p;
    int count;
} ZLLAverge;
static void avergeRelease(ZLLAverge averge) {
    if (averge.p) {
        free(averge.p);
    }
}
static ZLLAverge avergeCreate(int a[], int count) {
    size_t memory_size = count * sizeof(int);
    int *newA = (int *)malloc(memory_size);
    memcpy(newA, a, memory_size);
    ZLLAverge averge;
    averge.p = newA;
    averge.count = count;
    return averge;
}

注意順序,銷毀方法在前,創建方法在后。這種可以最大程度的提醒使用者正確的使用方法。

如果要在別的結構體中使用有指針的結構體

typedef struct {
    ZLLAverge averge;
    int topMargin;
} ZLLAttiStringValue;
static void attiStringValueRelease(ZLLAttiStringValue stringValue) {
    avergeRelease(stringValue.averge);
}
static ZLLAttiStringValue attiStringValueCreate(int a[], int count) {
    ZLLAttiStringValue stringValue;
    if (a) {
            stringValue.averge = avergeCreate(a, count);
    }
    return stringValue;
}

也要提供創建和銷毀方法。

小結

  • 注意不能在創建函數內部求count,只能通過外面傳進來,因為函數調用過程,sizeof(指針)返回的是指針的字節,而不是數組的長度。
  • 不能在結構體中使用OC對象類型,OC對象類型本質是個指針,是在堆上開辟內存空間了的,而在及結構體銷毀方法里,我們是沒法調用OC對象的銷毀方法的

我們把oc對象轉為cf對象來看下引用計數

@interface ZLLFont : UIFont

@end
@implementation ZLLFont
- (void)dealloc {
    NSLog(@"......");
}


@end
typedef struct {
    ZLLAverge averge;
    int topMargin;
    ZLLFont *font;
} ZLLAttiStringValue;
static void attiStringValueRelease(ZLLAttiStringValue stringValue) {
    avergeRelease(stringValue.averge);
    if (stringValue.font) {
        CFTypeRef objCF = (__bridge_retained  CFTypeRef)stringValue.font;
         NSLog(@"release --- 引用計數 --- %ld", CFGetRetainCount(objCF));
        CFRelease(objCF);
        NSLog(@"release --- 引用計數 --- %ld", CFGetRetainCount(objCF));
        stringValue.font = nil;
    }
}
static ZLLAttiStringValue attiStringValueCreate(int a[], int count) {
    ZLLAttiStringValue stringValue;
    if (a) {
        stringValue.averge = avergeCreate(a, count);
    }
    stringValue.font = [ZLLFont systemFontOfSize:12];
    return stringValue;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZLLAttiStringValue stringValue = attiStringValueCreate(nil, 0);
    
    attiStringValueRelease(stringValue);
}
//
release --- 引用計數 --- 4
release --- 引用計數 --- 3

嘗試了多次調用CFRelease也不行。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容

  • __block和__weak修飾符的區別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,352評論 0 6
  • 結構體是C/C++兩種語言中的基礎語法, C語言中的結構體只是一個存粹的數據集合類型的描述,它只有數據成員而沒有...
    歐陽大哥2013閱讀 4,461評論 2 30
  • 眼是心的一道窗 總是被安排朝向遠方 無論白晝還是月夜 只要天空足夠晴朗 開闔卻是要隨著心的感覺 時不時的也會被要求...
    陽光紅藍鉛筆閱讀 458評論 3 5
  • 發表于2010年11月13日 點一曲蚊香 沒有啤酒的原唱 心情被初雪凍僵了嗎 閬苑仙葩 是非真假...
    鄺鑒萍閱讀 156評論 0 4
  • (一) 梁遇春先生回憶徐志摩,講一個夜里他用一根紙煙向朋友點燃的煙取火,說道:“kiss the fire?!?吻...
    北海道章魚酥閱讀 733評論 0 6