2012-04-06 26 views
2

不完全確定我的問題標題描述了我想要做什麼,但想不出如何更好地說出它!我使用的是C,也許下面的僞代碼將描述我想要做的事:使用變量訪問一般結構成員

typedef struct obj 
{ 
    char *str1; 
    char *str2; 
    char *str3; 
} object; 

/* global variable */ 
object *glob; 

void black_box_function(local, member) ???? 
{ 
    /* Do something with glob->member and local->member */ 
} 

void main() 
{ 
    object *ob1, *ob2; 

    /* Initialise glob, ob1 and ob2 somewhere */ 

    black_box_function(ob1, str1); 
    black_box_function(ob2, str3); 

} 

希望,你可以看到我想要做的事。我有一個「黑盒子」功能,可以對特定的成員做某些事情,並且我需要能夠告訴黑盒子功能使用哪個成員。

我不想直接將該成員直接傳遞給函數,就像在此代碼中一樣,因爲這不會輕易地嵌入到其他代碼中。

black_box_function(ob1->member, glob->member) 
+1

爲什麼不是合適? – cnicutar 2012-04-06 11:08:14

+0

如果你的成員真的被稱爲'str1','str2'等(我讚賞可能只是作爲例證),那麼爲什麼不使用數組,並將索引傳遞給函數呢? – 2012-04-06 11:18:26

+0

是的,例證。其實,我正在使用別人寫的代碼,我不能輕易改變。所以我需要堅持現有的結構定義。 – 2012-04-06 11:56:25

回答

2

你可以做以下的魔法(使用GCC擴展):

#define black_box(local, member) black_box_function((local), __builtin_offsetof(object, member)) 

void black_box_function(object *local, int offset) 
{ 
    char *lmember = ((void *)local) + offset; 
    char *gmember = ((void *)global) + offset; 
    /* do stuff */ 
} 

但是,你必須事先知道你的會員的類型。請記住,C不是一種動態類型語言,因此您根本沒有運行時反思。

編輯:您可以實現offsetof()功能,而無需訴諸GCC的擴展,這樣的:

#define offsetof(type, field) ((int) (unsigned long) &((type *) 0)->field) 
+0

+1。即使你使用GCC擴展,這也是最接近OP的請求! – 2012-04-06 11:32:23

+0

@PavanManjunath:謝謝,'offsetof'功能可以通過指針投射魔法實現,不需要擴展。爲簡潔起見,我使用了內置的GCC版本 – C2H5OH 2012-04-06 11:34:02

+0

爲什麼要刪除GCC擴展方法?保持他們兩個。將它們命名爲方法1和方法2。我的+1是爲你的GCC擴展方法:) – 2012-04-06 11:42:33

2

也許你能爲你的結構創建存取功能,並通過這些訪問器函數指針參數,而不是成員直接傳遞

typedef struct 
{ 
    int a; 
    int b; 
} foo; 

typedef int* (*accessor)(foo*); 

int* get_a(foo* f) { return &f->a; } 
int* get_b(foo* f) { return &f->b; } 

void black_box_function(foo* object, accessor fn) 
{ 
    int* p = fn(object); 
} 

int main(void) 
{ 
    foo bar1; 
    foo bar2; 

    black_box_function(&bar1, get_a); 
    black_box_function(&bar2, get_b); 

    return 0; 
} 
+0

我喜歡這個建議 - 認爲它會很好地工作 - 謝謝! – 2012-04-06 11:58:12

1

,因爲所有的字符*,你可以重新定義結構,如:

typedef struct obj 
{ 
    char **str; // Array of c 
} object; 

然後你就可以從主發送的str索引要一起工作:

black_box_function(obj1, index) 

所以你可以在你的黑匣子裏像obj1->str[i]一樣。

Btw,black-box_function不會編譯。

附註:在你的黑匣子功能和編譯代碼上多一點信息/代碼可以更好地瞭解你正在嘗試做什麼。

+0

在我的例子中,所有的都是char *,但不一定在我的真實代碼中。我試圖提煉出我的問題的本質到一些簡單的... 感謝您的建議,雖然... – 2012-04-06 11:47:36