typedef用法和陷阱

来源:https://www.cnblogs.com/bluenightbreeze/archive/2019/09/02/11444457.html
-Advertisement-
Play Games

一、typedef的用法 1.用typedef來聲明新的類型名,來代替已有的類型名,也就是給類型起別名。比如 這種用法經常用來作為定義與平臺無關的類型,方便代碼的跨平臺移植。 例如,定義REAL類型為目標平臺精度最高的類型。 1>在支持long double的平臺上定義為: 註:long doubl ...


一、typedef的用法

1.用typedef來聲明新的類型名,來代替已有的類型名,也就是給類型起別名。比如

1 typedef float REAL; //用REAL來代表float類型
2 REAL a; //定義一個REAL類型的變數,等價於float a,即定義一個float類型的變數a

這種用法經常用來作為定義與平臺無關的類型,方便代碼的跨平臺移植。

例如,定義REAL類型為目標平臺精度最高的類型。

1>在支持long double的平臺上定義為:

typedef long double REAL; 

註:long double為C99增加的類型,ANSI C標準規定了double變數存儲為 IEEE 64 位(8 個位元組)浮點數值,但並未規定long double的確切精度,但規定long double的精度不少於double的精度。所以對於不同平臺long double可能有不同的實現,有的是8位元組,有的是10位元組,有的是12位元組或16位元組。關於具體的編譯器的情況, 可以通過 sizeof(long double)得知。

2>在不支持long double的平臺上改為

typedef double REAL; 

3>在double不支持的平臺上改為 

typedef float REAL; 

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

2.為自定義數據結構(如struct、union)定義簡潔易記的類型名。

比如:

struct data{
    int month;
    int day;
    int year;
}; //定義一個data的結構體

聲明結構體變數時,代碼如下

struct data birthday;

 

用typedef可以定義新的類型,代替上面的結構體類型

typedef struct data{
    int month;
    int day;
    int year;
}DATA; //定義一個data的結構體

DATA birthday; //定義一個DATA類型的變數birthday,等價於上面struct data類型

註:這種方法在一些代碼規範中是不推薦和禁止的,因為新的類型隱藏了具體的類型,不利於看代碼的人直觀瞭解到實際類型。

3.用typedef來聲明新的類型

1>可以用來簡化數組變數定義

typedef int ARR[10]; //定義類型ARR為含有10個元素的int數組
ARR arr_a, arr_b; //定義了兩個含有10個元素的int數組變數arr_a,arr_b

2>簡化指針變數的定義

typedef int* INT_P
INT_P p1,p2; //定義兩個int指針變數p1、p2

註意,下麵的定義容易引起錯誤,所以編程規範中禁止一次聲明多個變數

int* p1, p2; //p1為int*類型,p2為int類型
1 typedef char* STRING;
2 STRINT p; //p為字元串指針變數
3 STRINT s[10]; //s為指針數組,即s為一個含有10個元素的數組,每個元素是一個字元串指針
4 
5 typedef int (* POINTER)(); //聲明POINTTER為指向函數的指針類型,該函數返回值為int類型
6 POINTER p1,p2; //p1,p2均為函數指針變數;

4.為複雜的聲明定義一個新的簡單的別名。

int *(*a[5])(int, char*); //變數名為a,直接用一個新別名pFun替換a

typedef int *(*pFun)(int, char*); 
pFun a[5]; //定義一個含有5個函數指針的數組
void (*b[10]) (void (*)()); //原聲明,b為含有10個元素的函數指針數組,其參數為不帶參數的函數指針

typedef void (*pFunParam)();//聲明不帶參數的函數指針為類型pFunParam
typedef void (*pFunx)(pFunParam); //聲明pFunx為函數指針
pFunx b[10]; //函數指針數組b
1 doube(*)() (*e)[9]; //變數e為指針,該指針指向一個數組,該數組含有9個元素,每個元素為一個函數指針,該函數指針的返回值為double類型
2 簡化寫法:
3 typedef double(*pFuny)(); //聲明一個函數指針別名pFuny,返回類型為double
4 typedef pFuny (*pFunParamy)[9]; //聲明一個指針
5 pFunParamy e;//聲明變數e為pFunParamy類型

理解複雜聲明可用的“右左法則”:

從變數名看起,先往右,再往左,碰到一個圓括弧就調轉閱讀的方向;括弧內分析完就跳出括弧,還是按先右後左的順序,如此迴圈,直到整個聲明分析完。舉例:
int (*func)(int *p);
首先找到變數名func,外面有一對圓括弧,而且左邊是一個*號,這說明func是一個指針;然後跳出這個圓括弧,先看右邊,又遇到圓括弧,這說明(*func)是一個函數,所以func是一個指向這類函數的指針,即函數指針,這類函數具有int*類型的形參,返回值類型是int。
int (*func[5])(int *);
func右邊是一個[]運算符,說明func是具有5個元素的數組;func的左邊有一個*,說明func的元素是指針(註意這裡的*不是修飾func,而是修飾func[5]的,原因是[]運算符優先順序比*高,func先跟[]結合)。跳出這個括弧,看右邊,又遇到圓括弧,說明func數組的元素是函數類型的指針,它指向的函數具有int*類型的形參,返回值類型為int。

也可以記住2個模式:
type (*)(....)函數指針 
type (*)[]數組指針

二、typedef的陷阱

1.typedef是一種新類型的聲明,不是簡單的字元串替換,不同於#define

例如:

 

1 typedef char* STRING;
2 int strcmp(const STRING,const STRING);

 

在上面的代碼中,“const STRING” 是否相當於 “const char*” 呢?

答案是否定的,原因很簡單,typedef 是用來聲明一種新的類型,它不同於巨集,不是簡單的字元串替換。STRING已經是一種類型,const修改該類型為常量。因此,“const STRING”中的 const 給予了STRING常量屬性,也就是整個指針本身常量性,也即形成了常量指針“char*const(一個指向char的常量指針)”。

即它實際上相當於“char*const”,而不是“const char*(指向常量 char 的指針)”。當然,要想讓 const PCHAR 相當於 const char* 也很容易,如下麵的代碼所示:

 

 

typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);

 

因此,無論什麼時候,只要為指針聲明 typedef,那麼就應該在最終的 typedef 名稱中加一個 const,以使得該指針本身是常量。

2.typedef 和存儲類關鍵字(storage class specifier)

typedef在語法上是一個存儲類的關鍵字(如auto、extern、mutable、static、register等一樣),雖然它並不真正影響對象的存儲特性。

例如下麵的代碼會編譯報錯:

1 typedef static int INT_STATIC;

 

 

 

參考:

https://www.cnblogs.com/a-s-m/p/10995722.html

http://c.biancheng.net/view/298.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 盒子模型:(重點) 盒子模型(CSS框模型)規定了元素框處理元素內容、內邊距、邊框、外邊框等樣式 記住上面這一張圖!一定要記住!一定!一定! 內邊距、邊框和外邊距是可選參數屬性,預設值:0 ;很多元素由用戶代理樣式表設置外邊距和邊框,通過將元素的 margin外邊距和padding內邊距設置為 0 ...
  • jQuery介紹 在說jQuery之前,先說一個概念吧,什麼是JavaScript框架庫,其實就是一個普通的js文件,裡面封裝了很多函數或者說封裝了很多相容的代碼;當然啦,jQuery就是眾多庫的一員,那麼我們為什麼要學習jQuery呢,那就講一下他的特點; 1. 很好的解決了不同瀏覽器之間的相容性 ...
  • 1.判斷輸入值的長度 1.1 根據輸入值的類型不同,限制輸入值長度不同 此時需要使用自定義的校驗規則。 如長度要求:中文輸入5位,非中文10位 1 <FormItem label="名稱" {...formItemLayout}> 2 {getFieldDecorator('name', { 3 r ...
  • Node.js是一個基於 Chrome V8 引擎的 JavaScript 運行環境;Node.js使用一個事件驅動、非阻塞式 I/O 的模型,使其輕量且高效;Node.js的軟體包生態系統npm是全球最大的開源庫生態系統。本文詳細介紹了Node.js的安裝、配置及測試教程,希望對您有所幫助。 ...
  • 前言 Koa 應用程式是一個包含一組中間件函數的對象,它是按照類似堆棧的方式組織和執行的。 當一個中間件調用 next() 則該函數暫停並將控制傳遞給定義的下一個中間件。當在下游沒有更多的中間件執行後,堆棧將展開並且每個中間件恢復執行其上游行為。 以上兩句話,是我在官方文檔中找到其對 Koa 中間件 ...
  • 下載:curl -L https://get.daocloud.io/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 許可權:chm ...
  • 根據這個問題和答案 - Python multiprocessing.cpu_count()在4核Nvidia Jetson TK1上返回'1' - Python multiprocessing.cpu_count()在某些系統上的功能輸出反映了主動使用的CPU數量,而不是CPU的數量實際上可以通過 ...
  • 模塊導入 當文件夾中有這樣一個自定義的command模塊 在它的內部寫下下列代碼: 然後我們在command模塊中執行下列代碼: 我們如果在這段程式中反覆執行多次這一段代碼,這一個文件結果也只會被導入一次 調用command模塊中的方法fuc() 當我們寫這樣一個代碼的時候,電腦會先去找到這一個模 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...