內核 宏定義 offsetof

1. offsetof

1.1 offsetof介紹

定義:offsetof在linux內核的include/linux/stddef.h中定義。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

說明:獲得結構體(TYPE)的變量成員(MEMBER)在此結構體中的偏移量。
(01)  ( (TYPE *)0 )   將零轉型爲TYPE類型指針,即TYPE類型的指針的地址是0。
(02)  ((TYPE *)0)->MEMBER     訪問結構中的數據成員。
(03)  &( ( (TYPE *)0 )->MEMBER )     取出數據成員的地址。由於TYPE的地址是0,這裏獲取到的地址就是相對MEMBER在TYPE中的偏移。
(04)  (size_t)(&(((TYPE*)0)->MEMBER))     結果轉換類型。對於32位系統而言,size_t是unsigned int類型;對於64位系統而言,size_t是unsigned long類型。

1.2 offsetof示例
代碼(offsetof_test.c)

#include <stdio.h>

// 獲得結構體(TYPE)的變量成員(MEMBER)在此結構體中的偏移量。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

struct student
{
    char sex;
    int age;
    char name[20];
};

void main()
{
    int sex_offset, age_offset, name_offset;

    sex_offset = offsetof(struct student, sex);
    age_offset = offsetof(struct student, age);
    name_offset = offsetof(struct student, name);

    printf("sex_offset = %d\n", sex_offset);
    printf("age_offset = %d\n", age_offset);
    printf("name_offset = %d\n", name_offset);
}

結果

說明:簡單說說"爲什麼age的偏移值是4,而不是1"。我的運行環境是linux系統,32位的x86架構。這就意味着cpu的數據總線寬度爲32,每次能夠讀取4字節數據。gcc對代碼進行處理的時候,是按照4字節對齊的。所以,即使name_offset是char(一個字節)類型,但是它仍然是4字節對齊的!

1.3 offsetof圖解

TYPE是結構體,它代表"整體";而MEMBER是成員,它是整體中的某一部分。
將offsetof看作一個數學問題來看待,問題就相當簡單了:已知'整體'和該整體中'某一個部分',而計算該部分在整體中的偏移。

巨人的肩膀:https://www.cnblogs.com/skywang12345/p/3562146.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章