程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> typedef和#define的用法和差別

typedef和#define的用法和差別

編輯:關於C++

typedef和#define的用法和差別。本站提示廣大學習愛好者:(typedef和#define的用法和差別)文章只能為提供參考,不一定能成為您想要的結果。以下是typedef和#define的用法和差別正文


1、typedef的用法

在C/C++說話中,typedef經常使用來界說一個標識符及症結字的別號,它是說話編譯進程的一部門,但它其實不現實分派內存空間,實例像:

typedef    int       INT;
typedef    int       ARRAY[10];
typedef   (int*)   pINT;

typedef可以加強法式的可讀性,和標識符的靈巧性,但它也有“非直不雅性”等缺陷。

2、#define的用法

#define為一宏界說語句,平日用它來界說常量(包含無參量與帶參量),和用來完成那些“外面似和氣、面前一長串”的宏,它自己其實不在編譯進程中停止,而是在這之前(預處置進程)就曾經完成了,但也是以難以發明潛伏的毛病及其它代碼保護成績,它的實例像:

#define   INT             int
#define   TRUE         1
#define   Add(a,b)     ((a)+(b));
#define   Loop_10    for (int i=0; i<10; i++)

在Scott Meyer的Effective C++一書的條目1中有關於#define語句弊病的剖析,和好的替換辦法,年夜家可參看。

3、typedef與#define的差別

從以上的概念便也能根本清晰,typedef只是為了增長可讀性而為標識符另起的新稱號(僅僅只是個體名),而#define本來在C中是為了界說常量,到了C++,const、enum、inline的湧現使它也逐漸成了起別號的對象。有時很輕易弄不清晰與typedef二者究竟該用哪一個好,如#define INT int如許的語句,用typedef一樣可以完成,用哪一個好呢?我主意用typedef,由於在晚期的很多C編譯器中這條語句長短法的,只是當今的編譯器又做了擴大。為了盡量地兼容,普通都遵守#define界說“可讀”的常量和一些宏語句的義務,而typedef則經常使用來界說症結字、冗雜的類型的別號。

宏界說只是簡略的字符串代換(原地擴大),而typedef則不是原地擴大,它的新名字具有必定的封裝性,乃至於新定名的標識符具有更容易界說變量的功效。請看下面第一年夜點代碼的第三行:

typedef    (int*)      pINT;
和上面這行:
#define    pINT2    int*

後果雷同?實則分歧!理論中見差異:pINT a,b;的後果同int *a; int *b;表現界說了兩個整型指針變量。而pINT2 a,b;的後果同int *a, b;

表現界說了一個整型指針變量a和整型變量b。

typedef的四個用處和兩個圈套

用處一:
界說一品種型的別號,而不只是簡略的宏調換。可以用作同時聲明指針型的多個對象。好比:
char*   pa,   pb;     //   這多半不相符我們的意圖,它只聲清楚明了一個指向字符變量的指針,  
//   和一個字符變量;
以下則可行:
typedef   char*   PCHAR;     //   普通用年夜寫
PCHAR   pa,   pb;                 //   可行,同時聲清楚明了兩個指向字符變量的指針
固然:
char   *pa,   *pb;
也可行,但絕對來講沒有效typedef的情勢直不雅,特別在須要年夜量指針的處所,typedef的方法更省事。

用處二:
用在舊的C代碼中(詳細多舊沒有查),贊助struct。之前的代碼中,聲明struct新對象時,必需要帶上struct,即情勢為:   struct   構造名   對象名,如:
struct   tagPOINT1
{
        int   x;
        int   y;
};
struct   tagPOINT1   p1;  

而在C++中,則可以直接寫:構造名   對象名,即:
tagPOINT1   p1;

估量或人認為常常多寫一個struct太費事了,因而就創造了:
typedef   struct   tagPOINT
{
        int   x;
        int   y;
}POINT;

POINT   p1;   //   如許就比本來的方法少寫了一個struct,比擬省事,特別在年夜量應用的時刻

也許,在C++中,typedef的這類用處二不是很年夜,然則懂得了它,對控制之前的舊代碼照樣有贊助的,究竟我們在項目中有能夠會碰到較早些年月遺留上去的代碼。

用處三:
用typedef來界說與平台有關的類型。
好比界說一個叫   REAL   的浮點類型,在目的平台一上,讓它表現最高精度的類型為:
typedef   long   double   REAL;  
在不支撐   long   double   的平台二上,改成:
typedef   double   REAL;  
在連   double   都不支撐的平台三上,改成:
typedef   float   REAL;  
也就是說,當跨平台時,只需改下   typedef   自己就行,不消對其他源碼做任何修正。
尺度庫就普遍應用了這個技能,好比size_t。
別的,由於typedef是界說了一品種型的新別號,不是簡略的字符串調換,所以它比宏來得穩健(固然用宏有時也能夠完成以上的用處)。

用處四:
為龐雜的聲明界說一個新的簡略的別號。辦法是:在本來的聲明裡慢慢用別號調換一部門龐雜聲明,如斯輪回,把帶變量名的部門留到最初調換,獲得的就是原聲明的最簡化版。舉例:

1.   原聲明:int   *(*a[5])(int,   char*);
變量名為a,直接用一個新別號pFun調換a便可以了:
typedef   int   *(*pFun)(int,   char*);  
原聲明的最簡化版:
pFun   a[5];  

2.   原聲明:void   (*b[10])   (void   (*)());
變量名為b,先調換左邊部門括號裡的,pFunParam為別號一:
typedef   void   (*pFunParam)();
再調換右邊的變量b,pFunx為別號二:
typedef   void   (*pFunx)(pFunParam);
原聲明的最簡化版:
pFunx   b[10];

3.   原聲明: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[5])(int   *);
func左邊是一個[]運算符,解釋func是具有5個元素的數組;func的右邊有一個*,解釋func的元素是指針(留意這裡的*不是潤飾func,而是潤飾func[5]的,緣由是[]運算符優先級比*高,func先跟[]聯合)。跳出這個括號,看左邊,又碰到圓括號,解釋func數組的元素是函數類型的指針,它指向的函數具有int*類型的形參,前往值類型為int。

也能夠記住2個形式:
type   (*)(....)函數指針  
type   (*)[]數組指針  

---------------------------------

圈套一:
記住,typedef是界說了一品種型的新別號,分歧於宏,它不是簡略的字符串調換。好比:
先界說:
typedef   char*   PSTR;
然後:
int   mystrcmp(const   PSTR,   const   PSTR);

const   PSTR現實上相當於const   char*嗎?不是的,它現實上相當於char*   const。
緣由在於const賜與了全部指針自己以常量性,也就是構成了常量指針char*   const。
簡略來講,記住當const和typedef一路湧現時,typedef不會是簡略的字符串調換就行。

圈套二:
typedef在語法上是一個存儲類的症結字(如auto、extern、mutable、static、register等一樣),固然它其實不真正影響對象的存儲特征,如:
typedef   static   int   INT2;   //弗成行
編譯將掉敗,會提醒“指定了一個以上的存儲類”。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved