www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式微處理器
[導(dǎo)讀]1. typedef 的基本使用 1.1 typedef與結(jié)構(gòu)體的結(jié)合使用 typedef 是 C 語言的一個關(guān)鍵字,用來給某個類型起個別名,也就是給C語言中已經(jīng)存在的一個類型起一個新名字。大家在閱讀代碼的過程中,會經(jīng)常見到 typedef 與結(jié)構(gòu)體、聯(lián)合體、枚舉、函數(shù)指針聲明結(jié)合使

1. typedef 的基本使用

1.1 typedef與結(jié)構(gòu)體的結(jié)合使用

typedef 是 C 語言的一個關(guān)鍵字,用來給某個類型起個別名,也就是給C語言中已經(jīng)存在的一個類型起一個新名字。大家在閱讀代碼的過程中,會經(jīng)常見到 typedef 與結(jié)構(gòu)體、聯(lián)合體、枚舉、函數(shù)指針聲明結(jié)合使用。比如下面結(jié)構(gòu)體類型的聲明和使用:

struct student{char name[20];int age;float score;};struct student stu = {"wit", 20, 99};


在C語言中定義一個結(jié)構(gòu)體變量,我們通常的寫法是:

struct 結(jié)構(gòu)體名 變量名;

前面必須有一個struct關(guān)鍵字打前綴,編譯器才會理解你要定義的對象是一個結(jié)構(gòu)體變量。而在C++語言中,則不需要這么做,直接使用:結(jié)構(gòu)體名 變量名就可以了

struct student{char name[20];int age;float score; };int main (void){ student stu = {"wit", 20, 99};return 0;}

如果我們使用typedef,就可以給student聲明一個別名student_t和一個結(jié)構(gòu)體指針類型student_ptr,然后就可以直接使用student_t類型去定義一個結(jié)構(gòu)體變量,不用再寫struct,這樣會顯得代碼更加簡潔。

#include <stdio.h>typedef struct student{char name[20];int age;float score;}student_t, *student_ptr;
int main (void){student_t stu = {"wit", 20, 99};student_t *p1 = &stu; student_ptr p2 = &stu;printf ("name: %s\n", p1->name);printf ("name: %s\n", p2->name); return 0;}程序運行結(jié)果:witwit


1. 2 typedef 與數(shù)組的結(jié)合使用

typedef除了與結(jié)構(gòu)體結(jié)合使用外,還可以與數(shù)組結(jié)合使用。定義一個數(shù)組,通常我們使用int array[10];即可。我們也可以使用typedef先聲明一個數(shù)組類型,然后再使用這個類型去定義一個數(shù)組。

typedef int array_t[10]; array_t array;int main (void){array[9] = 100;printf ("array[9] = %d\n", array[9]);return 0;}

在上面的demo程序中,我們聲明了一個數(shù)組類型array_t,然后再使用該類型定義一個數(shù)組array,這個array效果其實就相當(dāng)于:int array[10]。

1.3 typedef 與指針的結(jié)合使用


typedef char * PCHAR;int main (void){//char * str = "學(xué)嵌入式"; PCHAR str = "學(xué)嵌入式";printf ("str: %s\n", str);return 0;}

在上面的demo程序中,PCHAR 的類型是 char *,我們使用PCHAR類型去定義一個變量str,其實就是一個char *類型的指針。

1.4 typedef與函數(shù)指針的結(jié)合使用

定義一個函數(shù)指針,我們通常采用下面的形式:

int (*func)(int a, int b);

我們同樣可以使用typedef聲明一個函數(shù)指針類型:func_t

typedef int (*func_t)(int a, int b);func_t fp; // 定義一個函數(shù)指針變量

寫個簡單的程序測試一下,運行OK:

typedef int (*func_t)(int a, int b);int sum (int a, int b){return a + b;} int main (void){func_t fp = sum;printf ("%d\n", fp(1,2));return 0;}

為了增加程序的可讀性,我們經(jīng)常在代碼中看到下面的聲明形式:

typedef int (func_t)(int a, int b);func_t *fp = sum;

函數(shù)都是有類型的,我們使用typedef給函數(shù)類型聲明一個新名稱:func_t。這樣聲明的好處是:即使你沒有看到func_t的定義,也能夠清楚地知道fp是一個函數(shù)指針,代碼的可讀性比上面的好。

1.5 typedef與枚舉的結(jié)合使用
typedef enum color{ red, white, black, green, color_num,} color_t;
int main (void){enum color color1 = red;color_t color2 = red;color_t color_number = color_num;printf ("color1: %d\n", color1);printf ("color2: %d\n", color2);printf ("color num: %d\n", color_number);return 0;}

枚舉與typedef的結(jié)合使用方法跟結(jié)構(gòu)體類似:可以使用typedef給枚舉類型color聲明一個新名稱color_t,然后使用這個類型就可以直接定義一個枚舉變量。

2. 使用typedef的優(yōu)勢

不同的項目,有不同的代碼風(fēng)格,也有不同的代碼“癖好”。看得代碼多了,你會發(fā)現(xiàn):有的代碼喜歡用宏,有的代碼喜歡使用typedef。那么,使用typedef到底有哪些好處呢?為什么很多人喜歡用它呢?

2.1 可以讓代碼更加清晰簡潔
typedef struct student{char name[20];int age;float score;}student_t, *student_ptr;
student_t stu = {"wit", 20, 99};student_t *p1 = &stu;student_ptr p2 = &stu;

如示例代碼所示,使用typedef,我們可以在定義一個結(jié)構(gòu)體、聯(lián)合、枚舉變量時,省去關(guān)鍵字struct,讓代碼更加簡潔。

2.2 增加代碼的可移植性

C語言的int類型,我們知道,在不同的編譯器和平臺下,所分配的存儲字長不一樣:可能是2個字節(jié),可能是4個字節(jié),也有可能是8個字節(jié)。如果我們在代碼中想定義一個固定長度的數(shù)據(jù)類型,此時使用int,在不同的平臺環(huán)境下運行可能會出現(xiàn)問題。為了應(yīng)付各種不同“脾氣”的編譯器,最好的辦法就是使用自定義數(shù)據(jù)類型,而不是使用C語言的內(nèi)置類型。

#ifdef PIC_16typedef unsigned long U32#elsetypedef unsigned int U32 #endif

在16位的 PIC 單片機中,int一般占2個字節(jié),long占4個字節(jié),而在32位的ARM環(huán)境下,int和long一般都是占4個字節(jié)。如果我們在代碼中想使用一個32位的固定長度的無符號類型,可以使用上面方式聲明一個U32的數(shù)據(jù)類型,在代碼中你可以放心大膽地使用U32。將代碼移植到不同的平臺時,直接修改這個聲明就可以了。

在Linux內(nèi)核、驅(qū)動、BSP 等跟底層架構(gòu)平臺密切相關(guān)的源碼中,我們會經(jīng)??吹竭@樣的數(shù)據(jù)類型,如size_t、U8、U16、U32。在一些網(wǎng)絡(luò)協(xié)議、網(wǎng)卡驅(qū)動等對字節(jié)寬度、大小端比較關(guān)注的地方,也會經(jīng)??吹絫ypedef使用得很頻繁。

2.3 比宏定義更好用

C語言的預(yù)處理指令#define用來定義一個宏,而typedef則用來聲明一種類型的別名。typedef跟宏相比,不僅僅是簡單的字符串替換,可以使用該類型同時定義多個同類型對象。

typedef char* PCHAR1;#define PCHAR2 char *
int main (void){ PCHAR1 pch1, pch2; PCHAR2 pch3, pch4;printf ("sizeof pch1: %d\n", sizeof(pch1));printf ("sizeof pch2: %d\n", sizeof(pch2));printf ("sizeof pch3: %d\n", sizeof(pch3));printf ("sizeof pch4: %d\n", sizeof(pch4));return 0;}

在上面的示例代碼中,我們想定義4個指向char類型的指針變量,然而運行結(jié)果卻是:

sizeof pch1: 4sizeof pch2: 4sizeof pch3: 4sizeof pch4: 1

本來我們想定義4個指向char類型的指針,但是 pch4 經(jīng)過預(yù)處理宏展開后,就變成成了一個字符型變量,而不是一個指針變量。而 PCHAR1 作為一種數(shù)據(jù)類型,在語法上其實就等價于相同類型的類型說明符關(guān)鍵字,因此可以在一行代碼中同時定義多個變量。上面的代碼其實就等價于:

char *pch1, *pch2;char *pch3, pch4;
2.4 讓復(fù)雜的指針聲明更加簡潔

一些復(fù)雜的指針聲明,如:函數(shù)指針、數(shù)組指針、指針數(shù)組的聲明,往往很復(fù)雜,可讀性差。比如下面函數(shù)指針數(shù)組的定義:

int *(*array[10])(int *p, int len, char name[]);

上面的指針數(shù)組定義,很多人一瞅估計就懵逼了。我們可以使用typedef優(yōu)化一下:先聲明一個函數(shù)指針類型func_ptr_t,接著再定義一個數(shù)組,就會更加清晰簡潔,可讀性就增加了不少:

typedef int *(*func_ptr_t)(int *p, int len, char name[]);func_ptr_t array[10];


3. 使用typedef需要注意的地方

通過上面的示例代碼,我們可以看到,使用typedef可以讓我們的代碼更加簡潔、可讀性更強一些。但是typedef也有很多坑,稍微不注意就可能翻車。下面分享一些使用typedef需要注意的一些細節(jié)。

3.1 typedef在語法上等價于關(guān)鍵字

我們使用typedef給已知的類型聲明一個別名,其在語法上其實就等價于該類型的類型說明符關(guān)鍵字,而不是像宏一樣,僅僅是簡單的字符串替換。舉一個例子大家就明白了,比如const和類型的混合使用:當(dāng)const和常見的類型(如:int、char) 一同修飾一個變量時,const和類型的位置可以互換。但是如果類型為指針,則const和指針類型不能互換,否則其修飾的變量類型就發(fā)生了變化,如常見的指針常量和常量指針:

char b = 10;char c = 20;int main (void){ char const *p1 = &b; //常量指針:*p1不可變,p1可變char *const p2 = &b; //指針常量:*p2可變,p2不可變  p1 = &c; //編譯正常  *p1 = 20; //error: assignment of read-only location  p2 = &c; //error: assignment of read-only variable`p2' *p2 = 20; //編譯正常return 0;}

當(dāng)typedef 和 const一起去修飾一個指針類型時,與宏定義的指針類型進行比較:

typedef char* PCHAR2;#define PCHAR1 char * char b = 10;char c = 20;int main (void){ const PCHAR1 p1 = &b;const PCHAR2 p2 = &b; p1 = &c; //編譯正常  *p1 = 20; //error: assignment of read-only location  p2 = &c; //error: assignment of read-only variable`p2' *p2 = 20; //編譯正常return 0;}

運行程序,你會發(fā)現(xiàn)跟上面的示例代碼遇到相同的編譯錯誤,原因在于宏展開僅僅是簡單的字符串替換:

const PCHAR1 p1 = &b; //宏展開后是一個常量指針const char * p1 = &b; //其中const與類型char的位置可以互換

而在使用PCHAR2定義的變量p2中,PCHAR2作為一個類型,位置可與const互換,const修飾的是指針變量p2的值,p2的值不能改變,是一個指針常量,但是*p2的值可以改變。

const PCHAR2 p2 = &b; //PCHAR2此時作為一個類型,與const可互換位置PCHAR2 const p2 = &b; //該語句等價于上條語句char * const p2 = &b; //const和PCHAR2一同修飾變量p2,const修飾的是p2!
3.2 typedef是一個存儲類關(guān)鍵字

沒想到吧,typedef在語法上是一個存儲類關(guān)鍵字!跟常見的存儲類關(guān)鍵字(如:auto、register、static、extern)一樣,在修飾一個變量時,不能同時使用一個以上的存儲類關(guān)鍵字,否則編譯會報錯:

typedef static char * PCHAR;//error: multiple storage classes in declaration of `PCHAR'

3.3 typedef 的作用域

跟宏的全局性相比,typedef作為一個存儲類關(guān)鍵字,是有作用域的。使用typedef聲明的類型跟普通變量一樣遵循作用域規(guī)則:包括代碼塊作用域、文件作用域等。

typedef char CHAR;
void func (void){#define PI 3.14typedef short CHAR;printf("sizeof CHAR in func: %d\n",sizeof(CHAR)); }
int main (void){ printf("sizeof CHAR in main: %d\n",sizeof(CHAR)); func();typedef int CHAR;printf("sizeof CHAR in main: %d\n",sizeof(CHAR));printf("PI:%f\n", PI); return 0;}

宏定義在預(yù)處理階段就已經(jīng)替換完畢,是全局性的,只要保證引用它的地方在定義之后就可以了。而使用typedef聲明的類型則跟普通變量一樣遵循作用域規(guī)則。上面代碼的運行結(jié)果為:

sizeof CHAR in main: 1sizeof CHAR in func: 2sizeof CHAR in main: 4PI:3.140000


4 如何避免typedef的濫用?

通過上面的學(xué)習(xí)我們可以看到:使用typedef可以讓我們的代碼更加簡潔、可讀性更好。在實際的編程中,越來越多的人也開始嘗試使用typedef,甚至到了“過猶不及”的濫用地步:但凡遇到結(jié)構(gòu)體、聯(lián)合、枚舉都要用個typedef封裝一下,不用就顯得你low、你菜、你的代碼沒水平。

其實typedef也有副作用,不一定非得處處都用它。比如上面我們封裝的STUDENT類型,當(dāng)你定義一個變量時:

STUDENT stu;

不看STUDENT的聲明,你知道stu的含義嗎?未必吧。而如果我們直接使用struct定義一個變量,則會更加清晰,讓你一下子就知道stu是個結(jié)構(gòu)體類型的變量:

struct student stu;

一般來講,當(dāng)遇到以下情形時,使用typedef可能會有用,否則可能會適得其反:

  • 創(chuàng)建一個新的數(shù)據(jù)類型

  • 跨平臺、指定長度的類型:如U32/U16/U8

  • 跟操作系統(tǒng)、BSP、網(wǎng)絡(luò)字寬相關(guān)的數(shù)據(jù)類型:如size_t、pid_t等

  • 不透明的數(shù)據(jù)類型:需要隱藏結(jié)構(gòu)體細節(jié),只能通過函數(shù)接口訪問的數(shù)據(jù)類型

在閱讀Linux內(nèi)核源碼過程中,你會發(fā)現(xiàn)大量使用了typedef,哪怕是簡單的int、long都使用了typedef。這是因為:Linux內(nèi)核源碼發(fā)展到今天,已經(jīng)支持了太多的平臺和CPU架構(gòu),為了保證數(shù)據(jù)的跨平臺性和可移植性,所以很多時候不得已使用了typedef,對一些數(shù)據(jù)指定固定長度:如U8/U16/U32等。但是內(nèi)核也不是到處到濫用,什么時候該用,什么不該用,也是有一定的規(guī)則要遵循的,具體大家可以看kernel Document中的 CodingStyle 中關(guān)于typedef的使用建議。(在此感謝“裸機思維”的推薦)

-END-




推薦閱讀



【01】C語言十大經(jīng)典排序算法(動態(tài)演示+代碼,值得收藏)
【02】C語言、嵌入式中幾個非常實用的宏技巧
【03】C語言最全入門筆記
【04】絕對能檢測你C語言基礎(chǔ)水平的5個面試題
【05】C語言為何不會過時?你需要掌握多少種語言?

免責(zé)聲明:整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除


 

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉