C語言關鍵字 -(typedef關鍵字)

2021-02-19 嵌入式Linux
1、來個笑話

趙本山在春晚有一個這樣的笑話,是這樣的

有一隻老虎,被蛇咬了一口,老虎急了,就想把這蛇踩死,追啊追追追,追到一個小河邊,這蛇鑽水裡去了,老虎就在河岸上就這麼等,老虎說,小樣的我就不信你不出來。不一會,從裡面鑽出來一隻王八,老虎上去就把它按住了,「小樣的你穿個馬甲(jiá)我就不認識你了?」

這就是那隻小烏龜

typedef關鍵字就是擅長做障眼法,任何其他類型遇上他就可以變身成其他的模樣,這麼厲害的關鍵字,我們可一定要供著,因為實在太牛了。

2、typedef 或者應該是typealias

typedef 從字面理解應該是type + define 意思就是重新定義數據類型,不過這種理解不正確,我們在學習Linux ,知道裡面有一個單詞叫做alias,就是別名的意思,把type理解成typealias就再好不過了。比如姚明,我們給他起了個別名叫做中國的巨人,或者科比,我們給他起了個別名叫做黑曼巴。
我們在做項目的時候,我們需要把很多數據類型放在一起,然後起一個新的名字,這個時候就需要typedef例如:

 typedef struct player
 {
     
 }Play_st,*Play_p;

A),struct player play1;和 Play_st play1;是一樣的
B),struct player *play2;和Play_p play2; Play_st *play2;是一樣的

大家對B的答案不知道有沒有疑惑,我們可以這樣理解,typedef AAAA BBBB;就是把AAAA的別名定義為BBBB,所以上面的,我們可以這樣理解

struct player {

struct player {

3、typedef 和存儲類關鍵字(storage class specifier)

這種說法是不是有點令人驚訝,typedef 就像 auto,extern,mutable,static,和 register 一樣,是一個存儲類關鍵字。這並不是說 typedef 會真正影響對象的存儲特性;它只是說在語句構成上,typedef 聲明看起來象 static,extern 等類型的變量聲明。下面將帶到一個陷阱:

  typedef static int FAST_COUNTER; 

  編譯通不過。問題出在你不能在聲明中有多個存儲類關鍵字。因為符號 typedef 已經佔據了存儲類關鍵字的位置,在 typedef 聲明中不能用 static(或任何其它存儲類關鍵字)。

4、用typedef來定義與平臺無關的類型

比如定義一個叫 REAL 的浮點類型,在目標平臺一上,讓它表示最高精度的類型為:

typedef long double REAL;

在不支持 long double 的平臺二上,改為:

typedef double REAL;

在連 double 都不支持的平臺三上,改為:

typedef float REAL;

也就是說,當跨平臺時,只要改下 typedef 本身就行,不用對其他源碼做任何修改。

標準庫就廣泛使用了這個技巧,比如size_t。另外,因為typedef是定義了一種類型的新別名,不是簡單的字符串替換,所以它比宏來得穩健。
這個優點在我們寫代碼的過程中可以減少不少代碼量哦,做嵌入式開發的同學,對於自己的一份驅動代碼,代碼如果寫的好的話,可以同時移植到其他平臺就非常容易。

5、為複雜的聲明定義一個新的簡單的別名

方法是:在原來的聲明裡逐步用別名替換一部分複雜聲明,如此循環,把帶變量名的部分留到最後替換,得到的就是原聲明的最簡化版。

例子一:

原聲明:void ());
變量名為b,先替換右邊部分括號裡的,pFunParam為別名一:

typedef void 

例子二:

原聲明:doube(*)() (*e)[9];
變量名為e,先替換左邊部分,pFuny為別名一:

typedef double(*pFuny)();
再替換右邊的變量e,pFunParamy為別名二

typedef pFuny (*pFunParamy)[9];
原聲明的最簡化版:

pFunParamy e;

理解複雜聲明可用的「右左法則」:從變量名看起,先往右,再往左,碰到一個圓括號

就調轉閱讀的方向;括號內分析完就跳出括號,還是按先右後左的順序,如此循環,直

到整個聲明分析完。

舉例:

int (*func)(int *p);

首先找到變量名func,外面有一對圓括號,而且左邊是一個號,這說明func是一個指針;然後跳出這個圓括號,先看右邊,又遇到圓括號,這說明(func)是一個函數,所以func是一個指向這類函數的指針,即函數指針,這類函數具有int*類型的形參,返回值類型是int。

int ;

func右邊是一個[]運算符,說明func是具有5個元素的數組;func的左邊有一個,說明func的元素是指針(注意這裡的不是修飾func,而是修飾func[5]的,原因是[]運算符優先級比高,func先跟[]結合)。跳出這個括號,看右邊,又遇到圓括號,說明func數組的元素是函數類型的指針,它指向的函數具有int類型的形參,返回值類型為int。

這種用法是比較複雜的,出現的頻率也不少,往往在看到這樣的用法卻不能理解,相信以上的解釋能有所幫助。

6、typedef 與#define 的區別

案例一:
通常講,typedef要比#define要好,特別是在有指針的場合。請看例子:

typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;

在上述的變量定義中,s1、s2、s3都被定義為char *,而s4則定義成了char,不是我們

所預期的指針變量,根本原因就在於#define只是簡單的字符串替換而typedef則是為一

個類型起新名字。

案例二:

下面的代碼中編譯器會報一個錯誤,你知道是哪個語句錯了嗎?

#include "stdio.h"

void main(void)
{
    typedef char * pStr;

    char string[4] = "abc";
    const char *p1 = string;
    const pStr p2 = string;

    p1++;
    p2++;
}

是p2++出錯了。這個問題再一次提醒我們:typedef和#define不同,它不是簡單的文本替換。上述代碼中const pStr p2並不等於const char * p2。const pStr p2和const long x本質上沒有區別,都是對變量進行只讀限制,只不過此處變量p2的數據類型是我們自己定義的而不是系統固有類型而已。因此,const pStr p2的含義是:限定數據類型為char *的變量p2為只讀,因此p2++錯誤。

那麼問題來了,為什麼p1++,沒有問題,p1++前面也有一個const,

#include "stdio.h"

void main(void)
{
    typedef char * pStr;

    char string[4] = "abc";
    const char *p1 = string;
    const pStr p2 = string;

    p1++;
    
    printf("%s\n",p1);
}

這就涉及下面這個概念

//const和類型的位置可以互換,如果類型為指針則不能隨意互換

比如:

const int i; 和 int const i; 這個是一樣的

所以我們在看看上面兩個語句

typedef char * pStr;

char string[4] ="abc";

const char *p1 = string; 

const pStr p2 = string; 

我們把上面的代碼改成下面的

#include "stdio.h"

void main(void)
{
    typedef char * pStr;

    char string[4] = "abc";
     char * const p1 = string;
    const pStr p2 = string;

    p1++;
    
    printf("%s\n",p1);
}

所以總結const修飾指針變量

const int *a;
int const *a;
int * const a;
const int * const a; 

相關焦點

  • 「C語言指針」起別名關鍵字typedef和結構體類型的恩怨情仇
    其中提到了起別名關鍵字typedef,在那裡我們只是簡單介紹過:在實際工作中,程式設計師們普遍使用它,但是並未展開去講細節。所以本文決定沿襲上一篇文章的思路,結合一些程序實例,細緻地展開討論typedef和結構體相碰產生的奇妙反應。
  • C語言 關鍵字(32+5+7)
    C語言32個關鍵字(C99新增5個、C11新增7個)按年份起始:auto break case char const continue default do double else enum
  • C/C++中常用的編程關鍵字
    關鍵字作用:關鍵字是C++中預先保留的單詞(標識符)在定義變量或者常量時候,不要用關鍵字C++關鍵字如下:在 C++ 中,還可用來指定使用另一語言進行連結,這時需要與特定的轉換符一起使用。目前僅支持 C轉換標記,來支持 C 編譯器連結。
  • C語言中volatile關鍵字的使用
    打開APP C語言中volatile關鍵字的使用 發表於 2018-03-17 11:55:00 volatile的意思是易變的
  • C語言中const關鍵字的妙用總結
    請看正文學習了多年的C語言,你對const關鍵字的使用全都掌握了嗎?在編程實踐中你對const的使用是否有困惑呢?今天就給大家一起來探討總結,期望能夠大家解惑並提供參考。C語言中const關鍵字是constant的縮寫,通常翻譯為常量、常數等,有些朋友一看到const關鍵字馬上就想到了常量。事實上在C語言中const功能很強大,它可以修飾變量、數組、指針、函數參數等。本文將針對上述幾種修飾功能詳細做一個總結。
  • 一步帶您了解C語言中的「register」關鍵字
    寄存器比內存訪問要快,因此可以使用register關鍵字將C程序中最常用的變量放入寄存器中。關鍵字register會向編譯器提示可以將給定變量放入寄存器中。編譯器可以選擇是否將其保存在寄存器中。通常,編譯器自己進行優化,然後將變量放入寄存器中。
  • C語言宏定義#define的理解與資料整理
    但是我們利用define來定義數值類型的數據,一般只是用來定義  常量 ,如果 要定義一些變量,則可以使用c語言中const這個關鍵字。我們已經討論了const 這個關鍵字,我們知道const 修飾的數據是有類型的,而define 宏定義的數據沒有類型。
  • C語言基礎(下)
    C語言的世界結構體類型什麼是結構體我們觀察現實世界的時候,可以發現很多的東西它都是由不同的部分組合起來的Student student = {"泱澈",&stu,gen};printf("%s\n", student.name);printf("%s\n", (student.s)->name);printf("%s\n", student.gen.ch);return 0;}結構體變量在作為參數傳遞的時候使用的是值傳遞typedef
  • DSP編程技巧之17---非常「關鍵」的關鍵字
    什麼是「關鍵字」?關鍵字就是已被C語言本身使用,不能作其它用途使用的字,例如關鍵字不能用作變量名、函數名等。那「關鍵字」到底有多關鍵?簡單得說,就是如果不掌握它們的使用方法,程序就不能按照我們的設計產生預期的結果。
  • goto關鍵字你不知道的"那些事"(C語言提升)
    好了,要進入今天的主題了,今天我們要討論的是C語言中相對比較冷門的知識關鍵字goto!    關鍵字goto從字面的意思就是"去哪裡"的意思,專業一點的話表示無條件跳轉的意思(有學過彙編的小夥伴應該會覺得非常像jump指令),在C語言中的使用格式是:goto label,表示跳轉到label的位置,並且我們的label一般都寫在語句的開頭,寫成label:的形式。
  • Java之final關鍵字詳解
    前言針對Java語言中的final關鍵字,想必都不陌生了。本來主要是來對final做關鍵字做一個總結。final關鍵字用法修飾類當用final去修飾一個類的時候,表示這個類不能被繼承。注意:a.c. 如果修飾的成員變量是基本類型,則表示這個變量的值不能改變。d. 如果修飾的成員變量是一個引用類型,則是說這個引用的地址的值不能修改,但是這個引用所指向的對象裡面的內容還是可以改變的。代碼:每日一題下面有關java代碼安全性的敘述哪些是對的?
  • 如何設置Twitter關鍵字定位?
    在此輸入企業的Twitter關鍵字,然後選擇"添加"或"排除"它們 Twitter關鍵字添加:如果某人在推文中包含該Twitter關鍵字或與該推文進行了互動,並且滿足企業的地理位置,語言,設備和性別定位,則有Twitter關鍵字資格被此廣告系列定位
  • 快速上手系列-C語言之基礎篇(一)
    吃飯用的筷子,到現在我都不知道它的由來,不知道它是在什麼歷史背景下誕生的有些東西還是有必要了解一下,比如,C語言所產生的代碼運行速度比彙編語言編寫的代碼運行速度稍慢一點,但還是有得一拼,同時C語言要比彙編語言編寫的代碼可讀性高,可移植性好。另外,相對於其他高級語言,比如C++、java、C#等來說,C語言編寫的代碼運行效率要高。
  • 一文解析Java常用關鍵字
    Java語言中final是一個關鍵字(key words),其表示的三個含義:final修飾的變量是常量,final修飾的類不可繼承,final修飾的方法不可重寫。 4.2.1.2 引用類型 (類、接口、數組) 引用類型為堆內存,一旦被final關鍵字修飾,則引用不再改變,但是引用所指向的對象是可以被修改的,Java語言並未提供任何方式使用對象恆定不變。
  • Google Ads|如何高效搜索關鍵字
    今天這篇文章我們就來談一下Google關鍵字是如何匹配,以及擴展關鍵字所用到的一些工具。Google搜索廣告,本質上就是關鍵字廣告,用戶只有在Google搜索框中輸入關鍵詞才能觸發對應的關鍵字,因此廣告關鍵字的確定是投放廣告的重中之重,其實整理收集關鍵詞的方法有很多,但是很多新手剛開始跑的時候,也就無所謂隨便添加了一些關鍵詞上去,其實這樣既浪費錢又浪費經歷。
  • C/C+編程筆記:在C+中如何調用C語言的代碼?你可以這樣做
    比如在C文件中存在一個函數func_c(), 該文件與C++的工程混編在一起時,可以直接在C++中調用C文件中的func_c();不需要做任何額外處理。 而在C語言中是沒有這個技術的,所以如果我們想要調用C語言開發的一些API,就需要使用 extern "C"修飾C語言的函數聲明。
  • 深入理解Java中的final關鍵字
    最後也有一些使用final關鍵字的實。final經常和static一起使用來聲明常量。1、final方法在編譯階段綁定,稱為靜態綁定(static binding),編譯時常量,永遠不可改變。2、運行期初始化,我們希望它不會改變。3、接口中聲明的所有變量本身是final的。
  • 你要的常用免費關鍵字搜索工具推薦!
    我們整理了一系列易於使用的關鍵字研究工具,它們可以為大家提供有價值的數據,以提高優化效果。最棒的是給大家介紹的都是免費工具。 所以,讓我們馬上開始吧!
  • 談論關鍵字密度分析法則
    在做搜尋引擎優化的同時,關鍵字通常由不同的人所用的字眼,但很少有人真正了解哪些關鍵字都與網站和搜尋引擎。這似乎明顯的是搜索發動機將是谷歌的關鍵字,但我們可以實際應用的定義關鍵字一般,將幫助我們理解?關鍵字實際上,或多或少,任何單詞在網頁上出現。 這些話 , 使自己的網頁。
  • 「JavaSE」關鍵字、保留字、標識符、分隔符
    1.關鍵字定義:被Java語言賦予了特殊含義,用做專門用途的字符串(單詞)特點:所有關鍵字都是小寫,TRUE、FALSE、NULL都不是關鍵字。2.保留字定義:現有Java版本尚未使用,但以後版本可能會作為關鍵字使用 保留字:goto、const3.標識符定義: