01、結構體定義
基本定義:結構體,通俗講就像是打包封裝,把一些有共同特征(比如同屬于某一類事物的屬性,往往是某種業務相關屬性的聚合)的變數封裝在內部,通過一定方法訪問修改內部變數,
結構體的定義:
第一種:只有結構體定義
struct stuff{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 };
第二種:附加該結構體型別的“結構體變數”的初始化的結構體定義,如下代碼也就是定義結構體時,直接定義一個變數
struct stuff{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }xiaoming;
其實這就相當于先定義結構體,再用結構體定義一個結構體變數:
struct stuff{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }; struct stuff xiaoming;
第三種:使用typedef關鍵字,可以將結構體變數定義時少寫一個struct,比較省事,
typedef struct stuff{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }stuff_s; stuff_s xiaoming;
使用typedef還可以進一步簡化,將結構體名也省略,這也是常用的方式
typedef struct{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }stuff_s; stuff_s xiaoming;
STM32的標準外設庫有大量這樣的應用,如下
typedef struct { uint32_t GPIO_Pin; GPIOMode_TypeDef GPIO_Mode; GPIOSpeed_TypeDef GPIO_Speed; GPIOOType_TypeDef GPIO_OType; GPIOPuPd_TypeDef GPIO_PuPd; }GPIO_InitTypeDef;
關于結構體指標定義問題,有很多的“騷操作”的寫法,我一般按照下面定義指標
stuff_s *cuerrent_student;
02、結構體初始化
在大部分應用中,一般都是定義結構體后,在代碼中進行初始化,如下所示
typedef struct{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }stuff_s; stuff_s xiaoming; void xiaoming_inf_init() { xiaoming.name = "xiaoming"; xiaoming.num = 1; xiaoming.age = 18.0; xiaoming.score = 100; }
當然也有可以定義時就進行資料初始化的
typedef struct{ char *name; //姓名 int num; //學號 int age; //年齡 float score; //成績 }stuff_s; stuff_s xiaoming={"xiaoming",1,18.0,100};
C99和C11為結構提供了指定初始化器(designatedinitializer),其初始化器使用點運算子和成員名,
關于C99和C11的知識可以看我之前的文章《C語言的發展》,在IAR和Keil中記得勾選C99的選項,
例如,只初始化xiaoming結構中的name成員,可以這樣做:
stuff_s xiaoming= { .name = "xiaoming" };
也可以按照任意順序使用指定初始化器:
stuff_s xiaoming= { .age = 18.0, .name = "xiaoming" };
這樣的賦值方式,在linux方式中很常見,以platform驅動框架為例:
static struct platform_driver leds_platform_driver = { .driver = { .name = "imx6ul-led", .of_match_table = leds_of_match, }, .probe = leds_probe, .remove = leds_remove, };
03、訪問結構體成員
結構體成員的訪問需要借助結構體成員運算子(.),如下
stuff_s xiaoming,xiaohong; void student_inf_init() { xiaoming.name = "xiaoming"; xiaoming.num = 1; xiaoming.age = 18.0; xiaoming.score = 100; xiaohong.name = "xiaohong"; xiaohong.num = xiaoming.num+1; }
使用指標時,使用(->)符號訪問結構體成員
stuff_s xiaoming,xiaohong; stuff_s *cuerrent_student; void student_inf_init() { xiaoming.name = "xiaoming"; xiaoming.num = 1; xiaoming.age = 18.0; xiaoming.score = 100; cuerrent_student = &xiaohong; cuerrent_student->name = "xiaohong"; cuerrent_student->num = xiaoming.num+1; }
04、列舉與結構體的結合
簡單介紹下列舉:有些資料的取值往往是有限的,只能是非常少量的整數,并且最好為每個值都取一個名字,以方便在后續代碼中使用,比如一個星期只有七天,一年只有十二個月,一個班每周有六門課程等,
當然,你可以用宏定義
#define Mon 1 #define Tues 2 #define Wed 3 #define Thurs 4 #define Fri 5 #define Sat 6 #define Sun 7
如果用了列舉則如下
enum week{ Mon, Tues, Wed, Thurs, Fri, Sat, Sun };
列舉是一種型別,通過它可以定義列舉變數:
enum week a, b, c;
那么列舉和結構體一起用會產生什么效果呢?假設我們要協議一個語音芯片的驅動,需要表示語音芯片的狀態
typedef enum//語音芯片狀態 { VOICE_INIT_OK = 0x4A, //語音芯片上電初始化成功后,自動回傳命令 VOICE_RECEIVE_OK = 0x41, //語音芯片收到正確的命令幀 VOICE_ORDER_ERROR= 0x45, //語音收到錯誤的命令幀 VOICE_BUSY = 0x4E, //語音忙(正在合成狀態) VOICE_FREE = 0x4F //語音空閑 } VOICE_STATUS; typedef struct { VOICE_STATUS status ; //!< 語音芯片狀態 Ouint32 delayTicks; //!< 播放時間 Ouint32 playtimes; //!< 播放次數 } voicechip_Para_S; voicechip_Para_S voicechip_Para;
那么改變語音芯片狀態時,我們可以按照下面這樣寫
voicechip_Para.status = VOICE_RECEIVE_OK;
判斷語音芯片狀態時,我們可以按照下面寫
if((voicechip_Para.status == VOICE_FREE)
當然,你用宏定義是可以的,代碼也很整潔,這里希望你能理解文章最開始的那句話:結構體是某種業務相關屬性的聚合,
05、騷操作
關于結構體有很多騷操作,如果全部總結下來,這篇文章就會很臃腫,例如結構體嵌套的騷操作,可以一邊定義結構體B,一邊就使用上:
struct A{ struct B{ int c; }b; struct B sb; }a;
對于這樣的情況,我一般主張能看懂就行,自己寫代碼時就少點這樣的騷操作
struct B{ int c; }b; struct A{ struct B sb; }a;
點擊查看專題:C語言進階
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/412789.html
標籤:嵌入式
上一篇:變數存放指定段
