數組
數組是需要使用連續內存時候申請的一種內存,int a[10],聲明定義必須制定大小
int a[]可作爲參數傳入是代表a的首地址
訪問數組內的數據:a[1]下表方式,其實也是一個地址取值,去a+1的地址上取值*(a+1)
一個數據+1代表,地址後移數據的類型大小sizeof(a)
連續內存申請:
結構體中的最後一個元素爲int buf[0],這時候buf是不佔內存大小的
當malloc申請大於結構體本身內存大小時候,buf就可以指向了後臺多餘內存的地址和類型
鏈表
鏈表用於不定長的不連續內存的申請
不定長:每加一個元素都是看時機的,所以每次都要malloc
不連續,每次malloc的時候只是一個元素,和前面元素不連續,就需要一根線連起來,不然我們就把前面的元素弄丟了
struct list {
struct list *prev,*next;
};
鏈表僅是一根線,線上有自己的數據類型mydata
struct mylist {
void *mydata;
struct list;
};
還需要解決的問題:添加一個,刪除一個,遍歷查找數據
struct inline void __list_add(struct list *new, struct list *prev, struct list *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
添加需要知道新的數據地址,要添加的地方,
需要建立關係:前一數據的後,後一數據的前,新數據的前,新數據的後
struct inline void list_add(struct list *new, struct list *head)
{
__list_add(new, head, head->next);
}
添加尾部,確定位置是鏈表頭的前一元素
struct inline void list_add_tail(struct list *new, struct list *head)
{
__list_add(new, head->prev, head);
}
刪除一個元素,需要確定關係刪除數據的前面數據的後,刪除數據的後面數據的前
struct inline void __list_del(struct list *prev, struct list *next)
{
prev->next = next;
next->prev = prev;
}
要刪除的元素需要鏈表賦值清零
struct inline void list_del(struct list *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (void *) 0;
entry->prev = (void *) 0;
}
遍歷,從頭開始遍歷,到循環到頭停止
開始賦值,pos=head->next,這裏head沒有mydata
條件:pos!=head
執行動作:pos=pos->next
safe:刪除當前節點時候,執行動作會有空指針,所以需要n預先存儲pos->next
//CPU提供的 prefetch 指令將數據放入緩存
#define list_for_each(pos,head) \
for (pos = head->next, prefetch(pos->next); pos != head;\
pos = pos->next, prefetch(pos->next))
#define list_for_each_prev(pos,head) \
for (pos = head->prev; pos != head; pos = pos->prev)
//因此只遍歷鏈表不刪除節點時可以使用前者,若有刪除節點的操作,則要使用後者
#define list_for_each_safe(pos, n, head) \
for (pos = head->next, n = pos->next; pos != head; pos = n, n = pos->next)
知道結構體內某一成員變量地址,求結構體地址
//上到下加法,下到上減法
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
type 0地址是結構體所在地址,那麼member就是絕對地址,member的相對地址ptr就可以求得結構體當前地址
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member)*__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })