C 語言中結構的指標算術
高等 C 語言簡介字串指標與陣列函數結構物件導向記憶體檔案錯誤處理巨集處理C 與組合語言資料結構動態字串動態陣列鏈結串列雜湊表開發環境MakeCygwinMinGWDevC++wxDevC++編譯器gcc 編譯器TinyCC 編譯器LCC 編譯器應用主題CGI 程式GNU 程式視窗程式影像處理練習題訊息相關網站參考文獻最新修改簡體版English |
在 C 語言當中,指標的內容就是記憶體位址,於是我們可以利用指標的算術,計算出某些具有特殊價值的數字,然後進行位址操作,以便定址到我們想要的內容上。 舉例而言,在 Linux 的鏈結串列中,就定義了下列的 offsetof() 巨集函數,可以讓我們計算出一個結構與其欄位間的距離, #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 事實上,offsetof() 這個巨集已經被納入到 ANSI C 的 <stddef.h> 表頭中,您也可以引用該表頭,而不需要自己實作。 如果我們要從欄位指標反求其母結構位址,則可參考下列 Linux 核心中的原始碼,使用 container_of() 函數 #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) 這樣的巨集函數要如何使用呢?請參考下列範例。 程式範例:結構中的指標運算檔案:structptr.c #include <stdio.h> #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) typedef struct { char name[20]; int age; } Person; // 以 Person 中的 age 欄位為例,說明 container_of() 函數的作法 // container_of(&p.age, Person, age) // typeof( ((Person *)0)->age ) is int // int *__mptr = (&p.age); // (Person *) ((char *) __mptr - offsetof(Person, age)) int main() { Person p = { .name="John", .age=40 }; size_t offset = offsetof(Person, age); printf("offset=0x%x\n", offset); printf("offsetof(Person,age)=0x%x\n", offsetof(Person, age)); printf("&p=%p\n", &p); printf("&p.age=%p\n", &p.age); printf("p.age=%d\n", *(&p.age)); printf("&p+1=%p\n", &p+1); printf("&((Person*)&p)[1]=%p\n", &((Person*)&p)[1]); char *cptr = (char*) &p; printf("cptr+1=%p\n", cptr+1); printf("cptr+20=%p\n", cptr+20); printf("*(int *)(cptr+20)=%d\n", *(int *)(cptr+20)); int *mptr = (&p.age); Person *pptr = (Person *) ((char *) mptr-20); printf("*pptr=%p\n", pptr); // int **agePtr; // agePtr = (int**) (&p+offset); // printf("agePtr=%p\n", agePtr); // printf("*(&p+offset)=%d\n", *agePtr); // printf("&p+offsetof(Person,age)=%p\n", &p+offset); // printf("container_of(&p.age,Person,age)=%p\n", container_of(&p.age, Person, age)); } 執行結果
|
page revision: 5, last edited: 01 Sep 2010 04:21
Post preview:
Close preview