C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)
示例:
typedef struct _user {char name[20];char sex[20];int age;struct list_head mylist;//自定義結構體里保存雙向循環鏈表頭結點 }user;如果知道mylist的地址,如何獲取user的地址呢?
可以這樣:
u = (user*)((int)pos1 - sizeof(user) + sizeof((((user*)0)->mylist)));使用mylist的地址pos1,減去user與mylist的容量大小之差,再將結果轉換回user*類型,最后得到的就是user u的地址
注意:對指針直接加減,是相對于這個指針它自身的類型的,要把指針地址轉換成實際數值再相加減
(user*)0用法可參考:C語言如何獲取結構體中指定元素的大小?sizeof ( (X*)0 ) -> Y)
ffffff
但是不得不考慮到可能存在對齊的情況,就是空間與實際存儲的數據大小不一致的情況,可見:C語言 如何計算結構體的大小
比如這里就發生了地址對齊:
char sex之后age之前空出了兩個字節的存儲空間,以滿足后面int類型大小的倍數,但是因為在mylist之后就沒發生過字節對齊的情況,(mylist存放的是prev* 和next*兩個指針),所以對結果不影響
但是如果mylist之后還存在特殊情況,用上面的方法還能計算出mylist和user真實的地址差嗎??
我們再來做個小測試:
&((user*)0)->mylist; &(((user*)0)->mylist); (int)&((user*)0)->mylist;
這個語法,實際上就是offsetof函數,但是我用不了這個函數不知道咋回事,直接把它源碼弄來!
可以看到,->是比&優先級高的,所以不用加括號()
offsetof()函數是啥,可以看這:C語言中 offsetof 的使用
這個函數可以求得結構體中元素(頭)相對于結構體(頭)的地址差!
所以我們想要通過元素(頭)地址求結構體(頭)地址,只要這樣即可:
u = (user*)((int)pos1 - (int)&((user*)0)->mylist);是不是又比我們開頭那會用的又簡單了很多???!!!
參考文章:C語言如何獲取結構體中指定元素的大小?sizeof ( (X*)0 ) -> Y)
完整泛型鏈表代碼:by jianggong
main.c不是main.cpp!!
#include <stdio.h> struct list_head {struct list_head* next;struct list_head* prev; };#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)//根據structd的成員獲取struct的地址 #define container_of(ptr, type, member) ((type *)(((char *)ptr) - (int)(&(((type*)0)->member))))//鏈表遍歷#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_prev(pos, head) \for (pos = (head)->prev; pos != (head); pos = pos->prev)#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)static inline void __list_add(struct list_head* new_,struct list_head* prev,struct list_head* next) {next->prev = new_;new_->next = next;new_->prev = prev;prev->next = new_; }static inline void list_add(struct list_head* new_, struct list_head* head) {__list_add(new_, head, head->next); }static inline void list_add_tail(struct list_head* new_, struct list_head* head) {__list_add(new_, head->prev, head); }static inline void __list_del(struct list_head* prev, struct list_head* next) {next->prev = prev;prev->next = next; }static inline void list_del(struct list_head* entry) {__list_del(entry->prev, entry->next); }typedef struct _user {char name[11];char sex[11];int age;struct list_head mylist;//自定義結構體里保存雙向循環鏈表頭結點 }user;typedef struct _records {char name[20];int type;struct list_head mylist;//自定義結構體里保存雙向循環鏈表頭結點 }records;int main() {//LIST_HEAD(header_task);//初始化頭結點struct list_head header_task1 = { &(header_task1), &(header_task1) };struct list_head header_task2 = { &(header_task2), &(header_task2) };user u1 = { "張麻子", "男", 40 };user u2 = { "牛魔王", "男", 36 };user u3 = { "蜘蛛精", "女", 28 };records r1 = {"張麻子", 1};records r2 = {"蜘蛛精", 2};records r3 = {"牛魔王", 1};//新建struct list_head* pos1;struct list_head* pos2;user* u;records* r;//頭插法list_add(&u1.mylist, &header_task1);list_add(&u2.mylist, &header_task1);list_add(&u3.mylist, &header_task1);list_add(&r1.mylist, &header_task2);list_add(&r2.mylist, &header_task2);list_add(&r3.mylist, &header_task2);//list_for_each(pos1, &header_task1) {// u = container_of(pos1, user, mylist);// printf("data is %d\n", u->age);//}for (pos1 = (&header_task1)->next; pos1 != (&header_task1); pos1 = pos1->next){//u = container_of(pos1, user, mylist);//u = ((user*)(((char*)pos1) - (int)(&(((user*)0)->mylist))));//u = (user*)((int)pos1 - sizeof(user) + sizeof((((user*)0)->mylist)));//&((user*)0)->mylist;//->優先級高于&u = (user*)((int)pos1 - (int)&((user*)0)->mylist);printf("data is %d\n", u->age);}printf("----------\n");list_del(&u2.mylist);list_for_each(pos1, &header_task1) {u = container_of(pos1, user, mylist);printf("data is %d\n", u->age);}printf("Hello World!\n");return 0; }運行結果:
data is 28 data is 36 data is 40 ---------- data is 28 data is 40 Hello World!總結
以上是生活随笔為你收集整理的C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言如何获取结构体中指定元素的大小?s
- 下一篇: C语言数据结构(大话数据结构——笔记1)