原文地址:http://www.blogfshare.com/typedef-and-struct.html
一、typedef的用法
①:定義一種類型的別名,但不是簡單的宏替換。
通常來說,typedef要比#define要好,特別是在有指針的場合:
typedef char *pStr1;
#define pStr2 char*;
pStr1 s1,s2;
pStr2 s3,s4;
在上述的變量定義中,s1、s2、s3都被定義爲char *,而s4則定義成了char,不是我們所預期的指針變量,根本原因就在於#define只是簡單的字符串替換而typedef則是爲一個類型起新名字。
先定義:
typedef char* PSTR;
然後:
int mystrcmp(const PSTR, const PSTR);
const PSTR實際上相當於const char*嗎?不是的,它實際上相當於char* const。
原因在於const給予了整個指針本身以常量性,也就是形成了常量指針char* const。
簡單來說,記住當const和typedef一起出現時,typedef不會是簡單的字符串替換就行。
②:用typedef來定義與平臺無關的類型。
比如定義一個叫 REAL 的浮點類型,在目標平臺一上,讓它表示最高精度的類型爲:
typedef long double REAL;
在不支持 long double 的平臺二上,改爲:
typedef double REAL;
在連 double 都不支持的平臺三上,改爲:
typedef float REAL;
也就是說,當跨平臺時,只要改下 typedef 本身就行,不用對其他源碼做任何修改。
標準庫就廣泛使用了這個技巧,比如size_t。
另外,因爲typedef是定義了一種類型的新別名,不是簡單的字符串替換,所以它比宏來得穩健(雖然用宏有時也可以完成以上的用途)。
③:爲複雜的聲明定義一個新的簡單的別名。
在原來的聲明裏逐步用別名替換一部分複雜聲明,如此循環,把帶變量名的部分留到最後替換,得到的就是原聲明的最簡化版。
原聲明:int *(*a[5])(int, char*);
變量名爲a,直接用一個新別名pFun替換a就可以了:
typedef int *(*pFun)(int, char*);
原聲明的最簡化版:
pFun a[5];
a本身是一個數組,裏面保存的是指針類型的元素。
④:和struct搭配使用
這裏另外用一個部分講解。
二、struct和typedef struct的區別
在C語言,聲明struct新對象時,必須要帶上struct,即形式爲: struct 結構名 對象名,如:
struct point{
int x;
int y;
};
struct point p;
而在C++中,則可以直接寫:結構名 對象名,即:
point p;
所以可以使用typedef和struct一起使用:
typedef struct point{
int x;
int y;
}Point;
Point p;
這樣就省去了struct。
在struct中定義自己的指針:
typedef struct point{
int x;
int y;
struct point *next;
}Point;
或者:
typedef struct point *Point;
struct point{
int x;
int y;
Point next;
};
在C++中可以直接:
typedef struct point{
int x;
int y;
point *next;
}Point;
struct在代碼中常見兩種形式:
struct A{
int x;
int y;
};
struct{
int x;
int y;
}A;
前一種是結構體類型定義,定義{}中的結構爲一個名稱是“A”的結構體。
使用:
A a;
a.x;
或者:
typedef struct TagA{
int x;
int y;
}A; //A爲TagA的別名,是等同的。
後者是結構體變量定義,以{}中的結構,定義一個名稱爲”A”的變量。這裏的結構體稱爲匿名結構體,是無法被直接引用的。
使用:
A.x;
或者:
typedef struct{
int x;
int y;
}A; //定義匿名結構體的別名爲A
注意上面兩種的使用方法!!!
最後注意:
typedef在語法上是一個存儲類的關鍵字(如auto、extern、mutable、static、register等一樣),雖然它並不真正影響對象的存儲特性,如:
typedef static int INT2; //不可行
編譯將失敗,會提示“指定了一個以上的存儲類”。