C 語言 struct 第一個成員變數的妙用

2022-09-12 15:00:48

一、雙重身份

如下定義了一個 School 結構體:

typedef struct School
{
    int a;
    int b;
}SCHOOL_S;

SCHOOL_S stSch;

下面我們來輸出一下 stSch 以及成員變數 a 和 b 的地址:

int main()
{
    printf("stSch 的地址[%p]\n", &stSch);
    printf("    a 的地址[%p]\n", &stSch.a);
    printf("    b 的地址[%p]\n", &stSch.b);

    return 0;
}

輸出結果如下:

有沒有發現什麼不得了的事情——結構體 school 的地址與第一個成員變數 a 的地址相同,也就是說變數 a 的地址既是 school * 型別,又是 int * 型別。腦海中突然冒出一個大膽的想法,如果我將 a 的地址強制型別轉化為 SCHOOL_S * 型別呢:

int main()
{
    stSch.a = 10;
    stSch.b = 20;

    SCHOOL_S *pstSch = (SCHOOL_S *)&stSch.a;
    printf("a = %d\n", pstSch->a);
    printf("b = %d\n", pstSch->b);

    return 0;
}

輸出結果如下:

Amazing~

二、妙用

通過上邊的小測試,我們發現了 struct 的第一個成員變數的地址有雙重身份,那麼該如何使用呢?

對於兩個不同的結構體:

typedef struct Teacher
{
    char name[10];     /* 姓名 */
    int id;            /* 職工編號 */
}TEACHER_S;

typedef struct School
{
    char name[10];      /* 校名 */
    int cnt;            /* 教職工個數 */
}SCHOOL_S;

SCHOOL_S school;
TEACHER_S teacher;
void Init()
{
    strncpy(stSchool.name, "School", sizeof(stSchool.name) - 1);
    stSchool.cnt = 1;

    strncpy(stTeacher.name, "Teacher", sizeof(stTeacher.name));
    stTeacher.id = 1;
}

如何在得知 school 的情況下得到 teacher 的資訊呢?你或許可以這麼做:在 School 中新增 Teacher 的指標變數,使其指向 teacher。

typedef struct School
{
    char name[10];      /* 校名 */
    int cnt;            /* 教職工個數 */
    struct Teacher *pstTeacher; /* 【Add】指向 Teacher 的指標變數 */
}SCHOOL_S;
int main()
{
    Init();
    stSchool.pstTeacher = &stTeacher;
}

這也不失為一種方法,但怎麼樣才能用到第一個成員變數的「雙重身份」這個資訊呢?

下面讓我們對結構體 School 和 Teacher 做個簡單修改:

typedef struct List
{
    struct List *next;
}LIST_S;

typedef struct Teacher
{
    LIST_S head;        /* 【Add】單連結串列頭結點 */
    char name[10];      /* 姓名 */
    int id;             /* 職工編號 */
}TEACHER_S;

typedef struct School
{
    LIST_S head;        /* 【Add】單連結串列頭結點 */
    char name[10];      /* 校名 */
    int cnt;            /* 教職工個數 */
}SCHOOL_S;
int main()
{
    Init();
    stSchool.head.next = &stTeacher.head;

    TEACHER_S *pstTeacher = (TEACHER_S *)stSchool.head.next;

    printf(" stTeacher 的地址為[%p]\n", &stTeacher);
    printf("pstTeacher 的地址為[%p]\n", pstTeacher);
    
    return 0;
}

輸出結果如下:

是不是很神奇~