C語言再學習 -- 關鍵字typedef
一、typedef 介紹
typedef為C語言的關鍵字,作用是為一種資料型別定義一個新名字。比如人們常常使用 typedef 來編寫更美觀和可讀的程式碼。所謂美觀,意指 tepedef 能隱藏笨拙的語法構造以及平臺相關的資料型別,從而增強可移植性以及未來的可維護性。
這裡的資料型別包括內部資料型別(int,char等)和自定義的資料型別(struct等)。 在程式設計中使用typedef目的一般有兩個,一個是給變數一個易記且意義明確的新名字,另一個是簡化一些比較複雜的型別宣告。
typedef 使用方法如下:
注意:typedef 並不建立新的型別。它僅僅為現有型別新增一個同義字。typedef existing_type new_type_name;
typedef的簡單應用:
typedef unsigned char BYTE;
BYTE b1, b2;
在這個型別定義之後,識別符號 BYTE 可作為型別 unsigned char 的縮寫。該定義的作用域取決於 typedef 語句所在的位置。如果定義是在一個函式內部,它的作用域是區域性的,限定在那個函式裡。如果定義是在函式外部,它將具有全域性作用域。
通常,這些定義使用大寫字母,以提醒使用者這個型別名稱實際上是一個符號縮寫。不過,您也可以使用小寫字母。
二、typedef 用法總結
1、typedef 與 define 區別
首先你要了解 typedef 和 define 的區別,巨集定義只是簡單的字串代換,是在預處理完成的,而typedef是在編譯時處理的,它不是作簡單的代換,而是對型別說明符重新命名。被命名的識別符號具有型別定義說明的功能。
請看下面的例子:
#define P1 int *
typedef (int *) P2
從形式上看這兩者相似,但在實際使用中卻不相同。
下面用P1、P2說明變數時就可以看出它們的區別:
P1 a, b; 在巨集代換後變成: int *a, b; 表示 a 是指向整型的指標變數,而 b 是整型變數。
P2 a, b; 表示a,b都是指向整型的指標變數。因為PIN2是一個型別說明符。
由這個例子可見,巨集定義雖然也可表示資料型別, 但畢竟是作字元代換。在使用時要分外小心,以避出錯。
總結,typedef和#define的不同之處:
1、與#define不同,typedef 給出的符號名稱僅限於對型別,而不是對值。
2、typedef 的解釋由編譯器,而不是是處理器執行。
3、雖然它的範圍有限,但在其受限範圍內,typedef 比 #define 更靈活。
2、常規變數型別定義
typedef 宣告可用來表示一個變數的含義。
例如:typedef unsigned char uchar
描述:uchar等價於unsigned char型別定義
uchar c宣告等於unsigned char c宣告
3、陣列型別定義
例如: typedef int array[2];
描述: array等價於 int [2]定義;
array a宣告等價於int a[2]宣告
擴充套件: typedef int array[M][N];
描述: array等價於 int [M][N]定義;
array a宣告等價於int a[M][N]宣告
4、指標型別定義
例如: typedef int *pointer;
描述: pointer等價於 int *定義;
pointer p宣告等價於int *p宣告
例如: typedef int *pointer[M];
描述: pointer等價於 int *[M]定義;
pointer p宣告等價於int *p[M]宣告
5、函式地址說明
描述: C把函式名字當做函式的首地址來對待,我們可以使用最簡單的方法得到函式地址
例如: 函式:int func(void);
unsigned long funcAddr=(unsigned long)func;
funcAddr的值是func函式的首地址
6、函式宣告
例如: typedef int func(void);
func等價於 int (void)型別函式
描述1: func f宣告等價於 int f(void)宣告,用於檔案的函式宣告
描述2: func *pf宣告等價於 int (*pf)(void)宣告,用於函式指標的宣告,見下一條
7、函式指標
例如: typedef int (*func)(void)
描述: func等價於int (*)(void)型別
func pf等價於int (*pf)(void)宣告,pf是一個函式指標變數
8、識別typedef的方法:
a).第一步。使用已知的型別定義替代 typdef 後面的名稱,直到只剩下一個名字不識別為正確
如typedef u32 (*func)(u8);
從上面的定義中找到 typedef __u32 u32; typedef __u8 u8
繼續找到 typedef unsigned int __u32; typedef unsigned char __u8;
替代位置名稱 typedef unsigned int (*func)(void);
現在只有func屬於未知
b).第二步.未知名字為定義型別,型別為取出名稱和 typedef 的所有部分,如上為
func等價於unsigned unsigned int (*)(unsigned char);
c).第三部.定義一個變數時,變數型別等價於把變數替代未知名字的位置所得到的型別
func f等價於unsigned unsigned int (*f)(unsigned char)
9、結構體定義
結構體的一般定義形式為:
標籤(tag)欄位允許為成員列表提供一個名字,這樣它就可以在後續的宣告中使用。標籤允許多個宣告使用同一個成員列表,並且建立同一種類型的結構。
- struct 標籤{
- 型別名1 成員名1;
- 型別名2 成員名2;
- ……
- 型別名n 成員名n;
- }結構體變數;
- struct Student{
- char name[20];//姓名
- int age;//年齡
- float height;//身高
- };
- struct Student stu //Student 為標籤 stu 為結構體變數
- struct Student{ //Student 可有可無
- char name[20];//姓名
- int age;//年齡
- float height;//身高
- }stu;
- typedefstruct Student{ //Student 可有可無
- char name[20];//姓名
- int age;//年齡
- float height;//身高
- }Stu; //Stu 為型別名
- Stu stu; //Stu 為型別名,stu 為結構體變數
- #include <stdio.h>
- #include <string.h>
- typedefstruct
- {
- int n;
- float m;
- char name[20];
- }Ptr;
- int main (void)
- {
- Ptr p;
- //Ptr p = {11, 12.9, "hello"};
- strcpy (p.name, "hello"); //注意字串不能直接賦值
- p.n = 11;
- p.m = 12.9;
- printf ("n = %d, name = %s, m = %g\n", p.n, p.name, p.m);
- return 0;
- }
- 輸出結果:
- n = 11, name = hello, m = 12.9
10、結構體指標
struct Node {
int data;
struct Node *nextptr;
};
使用 typede 上面的程式碼可以改寫為如下:
typedef struct Node pNode;
struct Node {
int data;
pNode *nextptr;
};
或者
typedef struct Node{
int data;
struct Node *nextptr;
}pNode;
三、typedef 用途
用途一:與#define的區別
typedef 行為有點像 #define 巨集,用其實際型別替代同義字。不同點是 typedef 在編譯時被解釋,
因此讓編譯器來應付超越前處理器能力的文字替換。
用途二:減少錯誤
定義一種型別的別名,而不只是簡單的巨集替換。可以用作同時宣告指標型的多個物件。比如:
[cpp] view plain copy print?- char* pa, pb; // 這多數不符合我們的意圖,它只聲明瞭一個指向字元變數的指標,
- // 和一個字元變數;
以下則可行:
[cpp] view plain copy print?- typedefchar* PCHAR;
- PCHAR pa, pb;
這種用法很有用,特別是char* pa, pb的定義,初學者往往認為是定義了兩個字元型指標,其實不是,而用typedef char* PCHAR就不會出現這樣的問題,減少了錯誤的發生。
用途三: 直觀簡潔
用在舊的C程式碼中,幫助struct。以前的程式碼中,宣告struct新物件時,必須要帶上struct,即形式為: struct 結構名物件名,如:
[cpp] view plain copy print?- struct tagPOINT1
- {
- int x;
- int y;
- };
- struct tagPOINT1 p1;
而在C++中,則可以直接寫:結構名物件名,即:tagPOINT1 p1;
[cpp] view plain copy print?- typedefstruct tagPOINT
- {
- int x;
- int y;
- }POINT;
POINT p1; // 這樣就比原來的方式少寫了一個struct,比較省事,尤其在大量使用的時候,或許,在C++中,typedef的這種用途二不是很大,但是理解了它,對掌握以前的舊程式碼還是有幫助的,畢竟我們在專案中有可能會遇到較早些年代遺留下來的程式碼。
用途四:平臺無關性
用typedef來定義與平臺無關的型別。
typedef 有另外一個重要的用途,那就是定義機器無關的型別,例如,你可以定義一個叫 REAL 的浮點型別,在目標機器上它可以獲得最高的精度: [cpp] view plain copy print?- typedeflongdouble REAL;
-
相關推薦
C語言再學習 -- 關鍵字typedef
一、typedef 介紹 typedef為C語言的關鍵字,作用是為一種資料型別定義一個新名字。比如人們常常使用 typedef 來編寫更美觀和可讀的程式碼。所謂美觀,意指 tepe
C語言再學習 -- 關鍵字struct(轉)
結構體的一般定義形式為: 標籤(tag)欄位允許為成員列表提供一個名字,這樣它就可以在後續的宣告中使用。標籤允許多個宣告使用同一個成員列表,並且建立同一種類型的結構。 struct 標籤{ 型別名1 成員名1; 型別名2 成員名2; …… 型別名n 成員名n; }結構體變數;
C語言再學習--關鍵字
C語言一共有32個關鍵字,如下表所示: 關鍵字 說明 auto 宣告自動變數 short 宣告短整型變數或函式 int
C語言再學習 -- 關鍵字volatile
上週確實事情挺多的,年會、公司聚餐,一到過年就有忙不完的事分心。還好C語言再學習總結的已經差不多了,年前也不展開別的了,接下來這十幾天、總結幾篇典型的面試題吧。 言歸正傳,接下來看看關鍵字 volatile。 一、volatile 介紹 Indicates that
C語言再學習 -- 儲存型別關鍵字
C語言中有 5 個作為儲存類說明符的關鍵字,分別是 auto、register、static、extern 以及 typedef。關鍵字typedef 與記憶體儲存無關,由於語法原因被歸入此類。現在簡單瞭解一下這五個儲存類說明符的關鍵字:說明符 auto 表明一個變數具有自
C語言再學習-定義變數
當我們在c語言裡建立一個變數的時候 int x = 5; int y = 6; 00C517B8 mov dword ptr [x],5 00C517BF mov dword ptr [y],6 實際上在彙編層面,
C語言再學習5-陣列與優化
什麼是陣列?為什麼要用陣列? 通俗來講,在記憶體中一塊連續儲存資料的叫陣列,陣列的每個子元素的寬度都一樣,並且只能為通用的資料型別做單位(char,short,int等等) 讓我們先定義一個數組,然後賦值: char arr1[2] = { 0 }; arr1
C語言再學習7-結構體
為什麼使用結構體? struct My { char name[20] = "如風斬嶽"; int age; char addr[50] ; int money; double Coordinates; //..... }; 當我們有這樣一種需求,
C語言再學習 -- 負數
有符號數的表示方法是由硬體決定,而不是由C決定的。有三種表示方法: 1、二進位制原碼 0000 0001 表示 1 1000 0001 表示 -1 這個方法有個缺點是有兩個零: +0 和 -0。這會引起混淆,而且用兩個位
C語言再學習 -- 檔案
檔案是什麼 一個檔案(file)通常就是磁碟上的一段命名的儲存區。C 將檔案看成是連續的位元組序列,其中每一個位元組都可以單獨地讀取。 二進位制和文字模式 1、在windows系統中,文字模式
C語言再學習 -- ASCII碼錶(轉)
ASCII碼錶第一部分:ASCII非列印控制字元表ASCII表上的數字0–31分配給了控制字元,用於控制像印表機等一些外圍裝置。例如,12代表換頁/新頁功能。此命令指示印表機跳到下一頁的開頭。(參詳ASCII碼錶中0-31)第二部分:ASCII列印字元數字 32–126 分配給了能在鍵盤上找到的字元,當您檢視
【 分類 】- C語言再學習
專欄達人 授予成功建立個人部落格專欄
C語言再學習 -- 詳解C++/C 面試題 1
對這篇文章記憶猶新,因為之前找工作面試的時候,遇到過一家公司就是用的這套面試題。現在就結合考查的知識點和我總結完 C 語言再學習後的深入理解,來詳細的講講我對這篇文章的總結。 一、請填寫BOOL ,
C語言再學習 -- 再論記憶體管理
但現在看來,缺少示例。從新再寫一篇文章,著重介紹常見記憶體錯誤、跨函式使用儲存區。開始吧,再論記憶體管理!!發生記憶體錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程式執行時才能捕捉到。而這些錯誤大多沒有明顯的症狀時隱時現增加了改錯的難度。一、常見的記憶體錯誤及
C語言再學習 -- 記憶體管理
malloc ( )函式: malloc ( ) 向系統申請分配指定size個位元組的記憶體空間。返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可
C語言再學習 -- 時間函式
gmtime函式:可以把time函式得到的結果按照格林尼治時間轉換成一個結構體localtime函式:可以把time函式得到的結果按照當前時區轉換成一個結構體asctime函式:可以把一個記錄時間的結構體轉換成字串,一般與上兩個函式合用的格林時間,與北京時間換算,/* 時間函式演示 */ #
C語言再學習 -- 再論陣列和指標
之前有總結指標陣列,但是現在看來總結的太簡單了。好多重要的知識點都是一帶而過的。本想在後面新增後來想想算了,還是再寫一篇文章來詳細介紹陣列和指標這對冤家吧。一開始覺得C語言再學習專欄都寫了五十篇了,現在
C語言再學習 -- NUL和NULL的區別
NUL 是ASCII 字符集中 '\0' 字元的名字,它的位元組模式為全 0。NULL 指一個其值為 0 的指標。它們都是整型值,其值也相同,所以它們可以互換使用。然而,你還是應該使用適當的常量,因為
C語言再學習 -- 段錯誤(核心已轉儲)
一、什麼是段錯誤?一旦一個程式發生了越界訪問,cpu 就會產生相應的保護,於是 segmentation fault 就出現了,通過上面的解釋,段錯誤應該就是訪問了不可訪問的記憶體,這個記憶體區要麼是不存在的,要麼是受到系統保護的,還有可能是缺少檔案或者檔案損壞。二、段錯誤產
C語言再學習 -- 詳解C++/C 面試題 2
(經典)C語言測試:想成為嵌入式程式設計師應知道的0x10個基本問題。1、用預處理指令#define 宣告一個常數,用以表明1年中有多少秒(忽略閏年問題) #define SENCONDS_PER_YE