<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
總結一句話:“加不加typedef,型別是一樣的",這句話可以這樣理解:
沒加typedef之前如果是個陣列,那麼加typedef之後就是陣列型別;
沒加typedef之前如果是個函數指標,那麼加typedef之後就是函數指標型別;
沒加typedef之前如果是個指標陣列,那麼加typedef之後就是指標陣列型別。
typedef char TA[5];//定義陣列型別 typedef char *TB[5];//定義指標陣列型別,TB定義的變數為含5個char*指標元素的陣列(指標陣列型別) typedef char *(TC[5]);//指標陣列型別,因為[]的結合優先順序最高,所以加不加()沒啥區別,TC等價於TB typedef char (*TD)[5];//陣列指標型別,TD指向一個5容量的char陣列
後文簡單介紹下指標陣列和陣列指標
1、給已定義的變數型別起個別名
(1)typedef unsigned char uin8_t; //uint8_t就是unsigned char的別名,這是最基礎的用法;
(2)結構體用法——作用是給struct __person起了個別名person_t,這種這種用法也很基礎;
struct __person { char name[20]; uint8_t age; uint8_t height; } typedef __person person_t; //以上兩段程式碼也可合併為一段,如下: typedef struct __person { char name[20]; uint8_t age; uint8_t height; }person_t;
2、定義函數指標型別
首先來看一下如何定義函數指標變數,然後再看如何定義函數指標型別。
(1)定義函數指標變數
定義了一個函數指標變數pFunc,它可以指向這樣的函數:返回值為int,形參為char*、int:
int (*pFunc)(char *frame, int len);
定義了5個函數指標變數:pFunc[0]、pFunc[1]···,它們都可以指向這樣的函數:返回值為int*,形參為int:
int *(*pFunc[5])(int len);
(2)定義函數指標型別
定義函數指標型別,必須使用typedef,方法就是,在“定義函數指標變數”前加上typedef。
typedef int (*pFunc_t)(char *frame, int len);//定義了一個型別pFunc_t
舉例:
typedef int (*pFunc_t)(char *frame, int len);//定義了一個型別pFunc_t int read_voltage(char *data, int len) { int voltage = 0; ···//其他功能程式碼 return voltage; } int main(void) { pFunc_t pHandler = read_voltage;//使用型別pFunc_t來定義函數指標變數 ···//其他功能程式碼 }
3、定義陣列指標型別
這個問題還是分兩步,先看如何定義陣列指標變數,再看如何定義陣列指標型別。
(1)定義陣列指標變數
int(*pArr)[5];//定義了一個陣列指標變數pArr,pArr可以指向一個int [5]的一維陣列
char(*pArr)[4][5];///定義了一個陣列指標變數pArr,pArr可以指向一個char[4][5]的二維陣列
char(*pArr)[4][5];///定義了一個陣列指標變數pArr,pArr可以指向一個char[4][5]的二維陣列
int(*pArr)[5];//pArr是一個指向含5個int元素的一維陣列的指標變數 int a[5] = {1,2,3,4,5}; int b[6] = {1,2,3,4,5,6}; pArr = &a;//完全合法,無警告 pArr = a;//發生編譯警告,賦值時型別不匹配:a的型別為int(*),而pArr的型別為int(*)[5] pArr = &a[0];//發生編譯警告,賦值時型別不匹配:a的型別為int(*),而pArr的型別為int(*)[5] pArr = &b;//發生編譯警告,賦值時型別不匹配:&b的型別為int(*)[6],而pArr的型別為int(*)[5] pArr = (int(*)[5])&b;//型別強制轉換為int(*)[5],完全合法,無警告
上面這個例子中,使用型別轉換時,程式碼的樣式略顯複雜,試想,我們如果強轉為一個結構體陣列的指標,那這個強轉的括號裡的內容得多長!這就直接影響了程式碼的可讀性,因此,強轉後的型別應該定義出來。
(2)定義陣列指標型別
如同上面定義函數指標型別的方法,直接在前面加typedef即可,例如:
typedef int (*pArr_t)[5];//定義了一個指標型別pArr_t,該型別的指標可以指向含5個int元素的陣列
typedef int(*pArr_t)[5];//定義一個指標型別,該型別的指標可以指向含5個int元素的一維陣列 int main(void) { int a[5] = {1,2,3,4,5}; int b[6] = {1,2,3,4,5,6}; pArr_t pA;//定義陣列指標變數pA pA= &a;//完全合法,無警告 pA= (pArr_t)&b;//型別強制轉換為pArr_t,完全合法,無警告 }
(3)定義陣列型別
如果我們想宣告一個含5個int元素的一維陣列,一般會這麼寫:int a[5];
如果我們想宣告多個含5個int元素的一維陣列,一般會這麼寫:int a1[5], a2[5], a3[5]···,或者 a[N][5]
可見,對於定義多個一維陣列,寫起來略顯複雜,這時,我們就應該把陣列定義為一個型別,例如:
typedef int arr_t[5];//定義了一個陣列型別arr_t,該型別的變數是個陣列。
typedef int arr_t[5]; int main(void) { arr_t d; //d是個陣列,這一行等價於: int d[5]; arr_t b1, b2, b3;//b1, b2, b3都是陣列 d[0] = 1; d[1] = 2; d[4] = 134; d[5] = 253;//編譯警告:下標越界 }
4、為複雜的宣告定義一個新的簡單的別名
為複雜的宣告定義一個新的簡單的別名。方法是:在原來的宣告裡逐步用別名替換一部分複雜宣告,如此迴圈,把帶變數名的部分留到最後替換,得到的就是原宣告的最簡化版。舉例:
int *(*a[5])(int, char*);//原宣告 typedef int *(*pFun)(int, char*); //變數名為a,直接用一個新別名pFun替換a就可以了 pFun a[5];//原宣告的最簡化版
void (*b[10]) (void (*)());//原宣告 typedef void (*pFunParam)();//變數名為b,先替換右邊部分括號裡的,pFunParam為別名一 typedef void (*pFunx)(pFunParam);//再替換左邊的變數b,pFunx為別名二 pFunx b[10];//原宣告的最簡化版
陷阱一:記住,typedef是定義了一種型別的新別名,不同於宏,它不是簡單的字串替換。
陷阱二:typedef在語法上是一個儲存類的關鍵字(如auto、extern、mutable、static、register等一樣),雖然它並不真正影響物件的儲存特性。
案例一:
通常講,typedef要比#define要好,特別是在有指標的場合。請看例子:
typedef char *pStr1; #define pStr2 char *; pStr1 s1, s2; pStr2 s3, s4;
在上述的變數定義中,s1、s2、s3都被定義為char *,而s4則定義成了char,不是我們所預期的指標變數,根本原因就在於#define只是簡單的字串替換而typedef則是為一個型別起新名字。
案例二:
下面的程式碼中編譯器會報一個錯誤,你知道是哪個語句錯了嗎?
typedef char * pStr; char str[4] = "abc"; const char *p1 = str; const pStr p2 = str; p1++; p2++;
是p2++出錯了。這個問題再一次提醒我們:typedef和#define不同,它不是簡單的文字替換。上述程式碼中const pStr p2並不等於const char * p2。const pStr p2和const long x本質上沒有區別,都是對變數進行唯讀限制,只不過此處變數p2的資料型別是我們自己定義的而不是系統固有型別而已。因此,const pStr p2的含義是:限定資料型別為pStr 的變數p2為唯讀,因此p2++錯誤。
對於指標陣列和陣列指標的概念,相信很多人經常會感到迷惑,見到二者一時不能分辨究竟對應哪一個才是對的。接下來我們來分析一下二者區別。
我們來看一下這個範例程式碼:
int *ptr1[10]; int (*ptr2)[10];
對於上述程式碼語句,你是否能分清哪一句程式碼宣告的是指標陣列,而哪一句程式碼宣告的又是陣列指標呢?
答案是第一行程式碼宣告的ptr1是一個指標陣列,陣列名為 ptr1,而“int*”修飾的是陣列的內容,該陣列包含 5 個 指向 int 型別 資料的指標。第二行程式碼宣告的ptr2則是一個 陣列的指標 ,指標變數名為 ptr2,而 int 修飾的是陣列的內容,即陣列的每個元素。即ptr2 是一個指標,它指向一個包含 5 個 int 型別資料的陣列。
這裡其實可以首先看*能否與前面的型別結合,能的話,內容就是結合後的內容。
到此這篇關於C++ typedef用法詳解的文章就介紹到這了,更多相關C++ typedef用法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45