中階C語言 結構體(typedef用法、多維結構體、指針、內嵌函數、賦值)

先上冷菜:複習結構體樣式

type A:

多年工作經驗告訴我這種方法最爲標準實用,牆裂推薦

    typedef struct Student
    {
	    int a;
    }Stu;

使用方法:

		Stu exam;

type B:

省略了struct後面的內容

    typedef struct
    {
	    int a;
    }Stu;

使用方法:

		Stu exam;

type C:

省略了最後分號前的定義

    typedef struct stu
    {
	    int a;
    };

使用方法:

		struct Student exam;

注意:這種方法編譯器可能會警告,但是能夠運行且正常讀取數據不發生段錯誤。
圖1
type D:不使用typedef的情況

typedef可以自定義化名稱,不使用它相當於直接操作原生的結構體。
1.將typeA中的typedef去掉,此時Stu已經沒意義了,注意不可以使用struct Stu exam

    struct Student
    {
	    int a;
    }Stu;

使用方法:

struct Student exam;

2.將typeB中的typedef去掉
這是直接創建結構體變量的形式,只能使用一次,顯然在實戰中基本沒有什麼用處。

    struct
    {
	    int a;
    }Stu;

3.將typeC中的typedef去掉
百度百科收錄了這種寫法,也是比較標準的,但是本人不推薦使用
    typedef struct stu
    {
    int a;
    };
使用方法:

struct Student exam;

冷菜總結:實際應用上使用TYPE A的場景極其繁多,真心只記住它就行。

熱菜來了:

A結構體指針

定義:
拿最經典的TYPE A,在分號前面增加了指針

    typedef struct Student
    {
	    int a;
    }Stu,*pStu;

使用方法:

pStu exam1;
Stu exam2;
exam1 = &exam2;
exam2.a = 1;
printf("%d",exam1->a);//輸出爲1

也可以不改變TYPE A
使用方法:

Stu *exam1;
Stu exam2;
exam1 = exam2;
exam2.a = 1;
printf("%d",exam1->a);//輸出爲1

結構體數組的指針使用

Stu exam[4];
pStu p;
p = exam;
p +=2;//等價於p = exam[1]

多維結構體

參考結構體數組的使用,區別在於之前+1就指向下一個結構體成員。這裏的+1理論上就是結構體單位大小所佔內存空間的偏移。
複雜式結構體TYPE I:內有函數指針

繼續拿最經典的TYPE A,加入函數指針

    typedef struct Student
    {
	    int a;
	    void (*fun)(int a);
    }Stu;

使用之前先定義一個引用的函數

void foo(int i){
	printf("%d",i);
}
	Stu exam;
	exam.fun = foo;//
	exam.fun(1);//調用引用的函數,輸出1

這個函數指針有點low,來個再複雜的,其實就是指針方面的知識了,還是挺有用的,直接貼圖
這裏寫圖片描述

複雜式結構體TYPE II:內部竟有本身
就是這麼神奇,繼續拿最經典的TYPE A,加入本身

    typedef struct Student
    {
	    int a;
		   struct Student *stu_exam;
    }Stu;

用法:

Stu exam;
Stu child;
child.a = 1;
exam.stu_exam=child;//exam內的“本身”是結構體child

那麼怎麼讀取child中的a元素值?

exam.stu_exam.a?

顯然不對,正確的做法是需要一個Stu類型的容器來裝child,這是抽象的,實體實現就是定義一個Stu指針指向child

Stu *p;
p = exam.stu_exam;//注意這裏使用了=,如果stu_exam是指針類型的,應該p = &exam.stu_exam;
printf("%d",p->a);//輸出a,大功告成

複雜式結構體TYPE III:以“.”開頭

static struct file_operations hello_flops = {
    .owner  =   THIS_MODULE,
    .open   =   hello_open,     
    .write  =   hello_write,
};

這是結構體初始化的一種方式,.的功能還是訪問參數。
按照通用的方法,可以寫成這樣

static struct file_operations hello_flops;
hello_flops.owner  =   THIS_MODULE;
hello_flops.open   =   hello_open;
hello_flops.write  =   hello_write;

這種樣式可以說把2步縮成一步了,省事並且更直觀。

這個聲明採用了標記化結構初始化語法。這種寫法是值得采用的,因爲它使驅動程序在結構的定義發生變化時更具有可移植性,並且使代碼更加緊湊且易讀。標記化的初始化方法允許對結構成員進行重新排列。在某些場合下,將頻繁被訪問的成員放在相同的硬件緩存行上,將大大提高性能。
複雜式結構體TYPE V:缺省賦值結構體成員

struct button_desc {
	int gpio;
	int number;
	char *name;	
	struct timer_list timer;
};

static struct button_desc buttons[] = {
	{ S5PV210_GPH2(0), 0, "KEY0" },
	{ S5PV210_GPH2(1), 1, "KEY1" },
	{ S5PV210_GPH2(2), 2, "KEY2" },
	{ S5PV210_GPH2(3), 3, "KEY3" },
	{ S5PV210_GPH3(0), 4, "KEY4" },
	{ S5PV210_GPH3(1), 5, "KEY5" },
	{ S5PV210_GPH3(2), 6, "KEY6" },
	{ S5PV210_GPH3(3), 7, "KEY7" },
};

首先定義了button_desc的結構體類型,然後申請了buttons結構體組,在進行賦值的時候發現內容不夠完整,{}內是3個變量,原定義是4個。結果一樣是可以使用的,指針不越界,因爲系統已經申請了內存,只不過timer部分的內存都是空的。

未完待續

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