首頁 後端開發 C#.Net教程 C語言中typedef的用法有哪些?

C語言中typedef的用法有哪些?

Jul 18, 2020 pm 02:23 PM
c語言

typedef的用法有:1、為基本資料型別定義新的型別名稱;2、為自訂資料型別(結構體、共用體和枚舉型別)定義簡潔的型別名稱;3、為陣列定義簡潔的型別名稱;4、為指標定義簡潔的名稱。

C語言中typedef的用法有哪些?

C語言允許使用者使用typedef 關鍵字來定義自己習慣的資料型別名稱,來取代系統預設的基本型別名稱、陣列型別名稱、指標型名稱與使用者自訂的結構型名稱、共用型名稱、枚舉型名稱等。

一旦使用者在程式中定義了自己的資料型別名稱,就可以在程式中用自己的資料型別名稱來定義變數的型別、陣列的型別、指標變數的型別與函數的型別等。

例如,C 語言在C99 之前並未提供布林類型,但我們可以使用typedef 關鍵字來定義一個簡單的布林類型,如下面的程式碼所示:

typedef int BOOL;
#define TRUE 1
#define FALSE 0
登入後複製

定義好之後,就可以像使用基本型別資料一樣使用它了,如下面的程式碼所示:

BOOL bflag=TRUE;
登入後複製

#typedef的4種用法

在實際使用中,typedef 的應用主要有以下4種。

1、為基本資料型別定義新的型別名

也就是說,系統預設的所有基本型別都可以利用typedef 關鍵字來重新定義型別名,範例程式碼如下所示:

typedef unsigned int COUNT;
登入後複製

而且,我們也可以使用這種方法來定義與平台無關的類型。例如,要定義一個叫REAL 的浮點類型,在目標平台一上,讓它表示最高精度的類型,即:

typedef long double REAL;
登入後複製

在不支援long double 的平台二上,改為:

typedef double REAL;
登入後複製

甚至還可以在連double 都不支援的平台三上,改為:

typedef float REAL;
登入後複製

這樣,當跨平台移植程式時,我們只需要修改一下typedef 的定義即可,而不用對其他原始碼做任何修改。其實,標準庫中廣泛地使用了這個技巧,例如size_t 在VC 2010 的crtdefs.h 檔案中的定義如下所示:

#ifndef _SIZE_T_DEFINED
#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
#define _SIZE_T_DEFINED
#endif
登入後複製

2、為自訂資料類型(結構體、共用體和枚舉型別)定義簡潔的型別名稱

以結構體為例,下面我們定義一個名為Point 的結構體:

struct Point
{
    double x;
    double y;
    double z;
};
登入後複製

在呼叫這個結構體時,我們必須像下面的程式碼這樣來呼叫這個結構體:

struct Point oPoint1={100,100,0};
struct Point oPoint2;
登入後複製

在這裡,結構體struct Point 為新的資料型別,在定義變數的時候均要向上面的呼叫方法一樣有保留字struct,而不能像int 和double 那樣直接使用Point 來定義變數。現在,我們利用typedef 定義這個結構體,如下面的程式碼所示:

typedef struct tagPoint
{
    double x;
    double y;
    double z;
} Point;
登入後複製

在上面的程式碼中,實際上完成了兩個動作:

1)、定義了一個新的結構類型,程式碼如下所示:

struct tagPoint
{
    double x;
    double y;
    double z;
} ;
登入後複製

其中,struct 關鍵字和tagPoint 一起構成了這個結構類型,無論是否存在typedef 關鍵字,這個結構都存在。

2)、使用typedef 為這個新的結構起了一個別名,叫Point,即:

typedef struct tagPoint Point
登入後複製

因此,現在你就可以像int 和double 那樣直接使用Point 定義變量,如下面的程式碼所示:

Point oPoint1={100,100,0};
Point oPoint2;
登入後複製

為了加深對typedef 的理解,我們再來看一個結構體例子,如下面的程式碼所示:

typedef struct tagNode
{
    char *pItem;
    pNode pNext;
} *pNode;
登入後複製

從表面上看,上面的範例程式碼與前面的定義方法相同,所以應該沒有什麼問題。但是編譯器卻報了一個錯誤,為什麼呢?莫非 C 語言不允許在結構中包含指向它自己的指標?

其實問題並非在於struct 定義的本身,大家應該都知道,C 語言是允許在結構中包含指向它自己的指標的,我們可以在建立鍊錶等資料結構的實作上看到很多這類別例子。那問題在哪裡呢?其實,根本問題還是在於 typedef 的應用。

在上面的程式碼中,新結構建立的過程中遇到了 pNext 聲明,其類型是 pNode。這裡要特別注意的是,pNode 表示的是該結構體的新別名。於是問題出現了,在結構體類型本身還沒有建立完成的時候,編譯器根本就不認識 pNode,因為這個結構體類型的新別名還不存在,所以自然就會報錯。因此,我們要做一些適當的調整,例如將結構體中的pNext 宣告修改成如下方式:

typedef struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
} *pNode;
登入後複製

或將struct 與typedef 分開定義,如下面的程式碼所示:

typedef struct tagNode *pNode;
struct tagNode
{
    char *pItem;
    pNode pNext;
};
登入後複製

在上面的程式碼中,我們同樣使用typedef 給一個還未完全宣告的型別tagNode 起了一個新別名。不過,雖然 C 語言編譯器完全支援這種做法,但不建議這樣做。建議還是使用以下規範定義方法:

struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
};
typedef struct tagNode *pNode;
登入後複製

3、为数组定义简洁的类型名称

它的定义方法很简单,与为基本数据类型定义新的别名方法一样,示例代码如下所示:

typedef int INT_ARRAY_100[100];
INT_ARRAY_100 arr;
登入後複製

4、为指针定义简洁的名称

对于指针,我们同样可以使用下面的方式来定义一个新的别名:

typedef char* PCHAR;
PCHAR pa;
登入後複製

对于上面这种简单的变量声明,使用 typedef 来定义一个新的别名或许会感觉意义不大,但在比较复杂的变量声明中,typedef 的优势马上就体现出来了,如下面的示例代码所示:

int *(*a[5])(int,char*);
登入後複製

对于上面变量的声明,如果我们使用 typdef 来给它定义一个别名,这会非常有意义,如下面的代码所示:

// PFun是我们创建的一个类型别名
typedef int *(*PFun)(int,char*);
// 使用定义的新类型来声明对象,等价于int*(*a[5])(int,char*);
PFun a[5];
登入後複製

小心使用 typedef 带来的陷阱

接下来看一个简单的 typedef 使用示例,如下面的代码所示:

typedef char* PCHAR;
int strcmp(const PCHAR,const PCHAR);
登入後複製

在上面的代码中,“const PCHAR” 是否相当于 “const char*” 呢?

答案是否定的,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“char*const(一个指向char的常量指针)”。即它实际上相当于“char*const”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:

typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);
登入後複製

其实,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。

还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:

typedef static int INT_STATIC;
登入後複製

不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”。

相关推荐:《c语言教程

以上是C語言中typedef的用法有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1246
24
C語言數據結構:樹和圖的數據表示與操作 C語言數據結構:樹和圖的數據表示與操作 Apr 04, 2025 am 11:18 AM

C語言數據結構:樹和圖的數據表示與操作樹是一個層次結構的數據結構由節點組成,每個節點包含一個數據元素和指向其子節點的指針二叉樹是一種特殊類型的樹,其中每個節點最多有兩個子節點數據表示structTreeNode{intdata;structTreeNode*left;structTreeNode*right;};操作創建樹遍歷樹(先序、中序、後序)搜索樹插入節點刪除節點圖是一個集合的數據結構,其中的元素是頂點,它們通過邊連接在一起邊可以是帶權或無權的數據表示鄰

C語言文件操作難題的幕後真相 C語言文件操作難題的幕後真相 Apr 04, 2025 am 11:24 AM

文件操作難題的真相:文件打開失敗:權限不足、路徑錯誤、文件被佔用。數據寫入失敗:緩衝區已滿、文件不可寫、磁盤空間不足。其他常見問題:文件遍歷緩慢、文本文件編碼不正確、二進製文件讀取錯誤。

debian readdir如何與其他工具集成 debian readdir如何與其他工具集成 Apr 13, 2025 am 09:42 AM

Debian系統中的readdir函數是用於讀取目錄內容的系統調用,常用於C語言編程。本文將介紹如何將readdir與其他工具集成,以增強其功能。方法一:C語言程序與管道結合首先,編寫一個C程序調用readdir函數並輸出結果:#include#include#includeintmain(intargc,char*argv[]){DIR*dir;structdirent*entry;if(argc!=2){

CS-第 3 週 CS-第 3 週 Apr 04, 2025 am 06:06 AM

算法是解決問題的指令集,其執行速度和內存佔用各不相同。編程中,許多算法都基於數據搜索和排序。本文將介紹幾種數據檢索和排序算法。線性搜索假設有一個數組[20,500,10,5,100,1,50],需要查找數字50。線性搜索算法會逐個檢查數組中的每個元素,直到找到目標值或遍歷完整個數組。算法流程圖如下:線性搜索的偽代碼如下:檢查每個元素:如果找到目標值:返回true返回falseC語言實現:#include#includeintmain(void){i

c語言如何輸出倒數 c語言如何輸出倒數 Apr 04, 2025 am 08:54 AM

如何在 C 語言中輸出倒數?回答:使用循環語句。步驟:1. 定義變量 n 存儲要輸出的倒數數字;2. 使用 while 循環持續打印 n 直到 n 小於 1;3. 在循環體內,打印出 n 的值;4. 在循環末尾,將 n 減去 1 以輸出下一個更小的倒數。

C語言多線程編程:新手指南與疑難解答 C語言多線程編程:新手指南與疑難解答 Apr 04, 2025 am 10:15 AM

C語言多線程編程指南:創建線程:使用pthread_create()函數,指定線程ID、屬性和線程函數。線程同步:通過互斥鎖、信號量和條件變量防止數據競爭。實戰案例:使用多線程計算斐波那契數,將任務分配給多個線程並同步結果。疑難解答:解決程序崩潰、線程停止響應和性能瓶頸等問題。

c語言函數的定義調用聲明格式怎麼搞 c語言函數的定義調用聲明格式怎麼搞 Apr 04, 2025 am 06:03 AM

C語言函數包含定義、調用和聲明。函數定義指定函數名、參數和返回類型,函數體實現功能;函數調用執行函數並提供參數;函數聲明告知編譯器函數類型。值傳遞用於參數傳遞,注意返回類型,保持一致的代碼風格,並在函數中處理錯誤。掌握這些知識有助於編寫優雅、健壯的C代碼。

C 中的整數:一點歷史 C 中的整數:一點歷史 Apr 04, 2025 am 06:09 AM

整數是編程中最基礎的數據類型,堪稱編程的基石。程序員的工作就是賦予這些數字意義,無論軟件多麼複雜,最終都歸結於整數運算,因為處理器只理解整數。為了表示負數,我們引入了二進制補碼;為了表示小數,我們創造了科學計數法,於是有了浮點數。但歸根結底,一切仍然離不開0和1。整數的簡史在C語言中,int幾乎是默認類型。儘管編譯器可能會發出警告,但在許多情況下,你仍然可以寫下這樣的代碼:main(void){return0;}從技術角度來看,這與以下代碼等效:intmain(void){return0;}這種

See all articles