2017-03-02 90 views
0

我得到了下面的代碼:的typedef不透明的指針,不透明的指針

// file external_module.h 
typedef externaldata * externalhdl; // opaque pointer 
externalhdl external_Create(); 

// file internal_module.h 
typedef internaldata * internalhdl; // opaque pointer 
internalhdl internal_Create(); 

我想什麼做的是使用一個外部模塊的不透明指針作爲一個不透明的指針我的模塊裏面保存unessasary allocs 。目前我的解決辦法執行力度是:

typedef struct {externalhdl e} internaldata; 

internalhdl internal_Create() 
{ 
    internalhdl p = (internaldata*) malloc (sizeof(internaldata)); 
    p.e = external_Create(); 
    return p; 
} 

我想這樣做的是使用類似:

typedef ??? internaldata; //Don't know how 

internalhdl internal_Create() 
{ 
    return external_Create(); 
} 

從我的角度來看,這應該是可能的,因爲兩者都是指針,但我需要得到它警告免費?謝謝你的幫助。

+0

爲什麼不創建頭文件,您可以在其中定義此結構,並將此文件包含到所有源代碼中? – betontalpfa

+8

不,你這樣做**不是**想要這樣做!你根本不想'輸入'一個opject指針!最清楚的是:**永遠不會**'typedef'指向數據類型的指針!哦,'typedef'完全與內存分配有關。並提供[mcve]。你的代碼結構和你的問題並不清楚。從你表現出來看起來好像你迷失在你的個人'typedef'地獄裏。 – Olaf

+1

@betontalpfa:這不是_opaque_類型背後的想法。只是它不應該是'typedef'ed的指針。 – Olaf

回答

0

在我看來,你需要考慮的最重要的事情是,你將獲得絕對的東西,但是在做這樣的事情時會變得暗淡一些,並且你想要一個指向另一種類型的指針的指針。如果它是一個不透明的poitner,那麼它對於typedef沒有任何意義,因爲你永遠不會訪問底層結構的成員,它很可能會作爲void *指針傳遞,但是當你分配它時,你必須知道它是鍵入是因爲編譯器需要知道它的大小和佈局以便正確分配它(例如,正確對齊,否則將不可能,否則)。

如果你不想重複使用sizeof運營商分配正確的尺寸有兩種可能的方法

  1. 使用宏

    #define allocate(x) x = malloc(sizeof(*x)) 
    

    然後

    my_type *x; 
    allocate(x); 
    

    但這是h可怕和不清楚。

  2. 使用分配函數,

    my_type * 
    my_type_alloc() 
    { 
        return malloc(sizeof(my_type)); 
    } 
    

    這樣

    my_type *x; 
    x = my_type_allocate(); 
    

    這是乾淨和簡單,你不能這樣做不對。

注意,返回相應的指針類型只是確保你不會不小心做一些事情,可能會導致不確定的行爲,但分配函數可以簡單地返回void *,他們將工作,這就是爲什麼我沒有投malloc()「 s的回報值。

語法糖是一些你必須非常小心的事情,因爲有時你看起來像簡化和改進了語法,當你所做的事是從程序員那裏讀取你的代碼的重要信息,程序員甚至可能是你自己編寫代碼後的一段時間。

而您的解決方法實際上正在導致一個不必要的分配。事實上,當你最終理解poitners時,你將會真正避免不必要的分配,因爲當你只能從中讀取數據時,不會複製數據。


在這兩種情況下進行分配之後,以確保您可以訪問這些指針,而不會導致不確定的行爲

0

,你應該檢查NULL這似乎你是在正確的軌道上在設計方面,這只是一個值得懷疑的實現。正如評論中所提到的,你不應該隱藏typedefs背後的指針,而opaque指針也不例外。如果來電者認爲,這些都是分配的變量,他們可能會決定做愚蠢的事情是這樣的:

set_obj(obj1, "foo"); // set private data to something 
memcpy(&obj2, &obj1); // take a hardcopy of the data (or so we thought) 
set_obj(obj1, "bar"); // set private data to something else 
print_obj(obj2);  // prints "bar", wtf!!! 

所以,不要隱藏指針。 稍作修改,你應該得到的代碼按預期方式工作:

external.h

typedef struct external_t external_t; 

external_t* external_create (/* parameters here */); 

external.c

#include "external.h" 

external_t* external_create (/* parameters here */) 
{ 
    external_t* ext = malloc(sizeof *ext); 
    /* initialize stuff here */ 
    return ext; 
} 

internal.h

#include "external.h" 

typedef struct internal_t internal_t; 

internal_t* internal_create (/* parameters here */); 

內部.c

#include "internal.h" 

struct internal_t 
{ 
    external_t* ext; 
}; 

internal_t* internal_create (/* parameters here */) 
{ 
    internal_t* inter = malloc(sizeof *inter); 
    inter->ext = external_create (/* parameters here */); 
    if(inter->ext == NULL) 
    { 
    return NULL; 
    } 
    /* initialize stuff here */ 
    return inter; 
} 

調用者也必須使用指針。


此外,沒有必要施放malloc的結果。擊敗這裏的死馬:
Do I cast the result of malloc?