typedef與#define的區別


1.  typedef

typedef故名思意就是類型定義的意思,但是它並不是定義一個新的類型而是給已有的類型起一個別名,在這一點上與引用的含義類似,引用是變量或對象的別名,而typedef定義的是類型的別名typedef的作用主要有兩點:


1.1  簡化複雜的類型聲明

簡化複雜的類型聲明,或給已有類型起一含義明確的別名;如:

typedef bool (*FuncPointer)(intdouble); //聲明瞭一個返回 bool 類型並帶有兩個(int和double)形參的函數的指針類型FuncPointer

FuncPointer pFunc; //聲明瞭一個FuncPointer類型的函數指針對象pFunc


1.2  定義與平臺無關的類型

定義與平臺無關的類型,屏蔽不同平臺的類型差異化;如:

typedef來定義與平臺無關的類型。

比如定義一個叫 REAL 的浮點類型,在目標平臺一上,讓它表示最高精度的類型爲:

typedef long double REAL;

在不支持 long double 的平臺二上,改爲:

typedef double REAL;

在連 double 都不支持的平臺三上,改爲:

typedef float REAL;

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

標準庫就廣泛使用了這個技巧,比如size_t。另外,因爲typedef是定義了一種類型的新別名,不是簡單的字符串替換,所以它比宏來得穩健。


1.3  struct的結合使用

C++中,structclass的作用相同,就是默認的訪問權限不同,struct默認爲public,而class默認爲private的。

【例1.3.1】:

  1. struct Person  
  2. {  
  3.     string name;  
  4.     int age;  
  5.     float height;  
  6. };  
  7. Person person;  
struct Person
{
    string name;
    int age;
    float height;
};
Person person;

定義一個Struct的類型Person,定義一個Person的對象person


或者

  1. struct Person  
  2. {  
  3.     string name;  
  4.     int age;  
  5.     float height;  
  6. }person;  
struct Person
{
    string name;
    int age;
    float height;
}person;

定義一個Struct的類型Person,在定義的同時還聲明瞭一個Person的對象person

 


但是在C語言中,struct的定義和聲明要用typedef

【例1.3.2】:

  1. typedef struct __Person  
  2. {  
  3.     string name;  
  4.     int age;  
  5.     float height;  
  6. }Person;    //這是Person是結構體的一個別名  
  7. Person person;  
typedef struct __Person
{
    string name;
    int age;
    float height;
}Person;    //這是Person是結構體的一個別名
Person person;

如果沒有typedef就必須用struct Person person;來聲明,如:

【例1.3.3

  1. struct Person  
  2. {  
  3.     string name;  
  4.     int age;  
  5.     float height;  
  6. };  
  7. struct Person person;  
struct Person
{
    string name;
    int age;
    float height;
};
struct Person person;

  1. struct Person  
  2. {  
  3.     string name;  
  4.     int age;  
  5.     float height;  
  6. }person;    //person是Person的對象  
struct Person
{
    string name;
    int age;
    float height;
}person;    //person是Person的對象


 

2.  typedef與#define的區別


2.1.  執行時間不同

關鍵字typedef在編譯階段有效,由於是在編譯階段,因此typedef有類型檢查的功能。

#define則是宏定義,發生在預處理階段,也就是編譯之前,它只進行簡單而機械的字符串替換,而不進行任何檢查。

【例2.1.1typedef會做相應的類型檢查:

  1. typedef unsigned int UINT;  
  2.   
  3. void func()  
  4. {  
  5.     UINT value = “abc”// error C2440: ‘initializing’ : cannot convert from ‘const char [4]’ to ‘UINT’  
  6.     cout << value << endl;  
  7. }  
typedef unsigned int UINT;

void func()
{
    UINT value = "abc"; // error C2440: 'initializing' : cannot convert from 'const char [4]' to 'UINT'
    cout << value << endl;
}

 【例2.1.2#define不做類型檢查:

  1. //#define用法例子:  
  2. #define f(x) x*x  
  3. int main()  
  4. {  
  5.     int a=6, b=2, c;  
  6.     c=f(a) / f(b);  
  7.     printf(”%d\n”, c);  
  8.     return 0;  
  9. }  
//#define用法例子:




define f(x) x*x

int main()
{
int a=6, b=2, c;
c=f(a) / f(b);
printf("%d\n", c);
return 0;
}

程序的輸出結果是: 36,根本原因就在於#define只是簡單的字符串替換。

 

2.2.  功能有差異

typedef用來定義類型的別名,定義與平臺無關的數據類型,與struct的結合使用等。

#define不只是可以爲類型取別名,還可以定義常量、變量、編譯開關等。

 

2.3 作用域不同

#define沒有作用域的限制,只要是之前預定義過的宏,在以後的程序中都可以使用。

typedef有自己的作用域。

【例2.3.1沒有作用域的限制,只要是之前預定義過就可以

  1. void func1()  
  2. {  
  3.     #define HW “HelloWorld”;  
  4. }  
  5.   
  6. void func2()  
  7. {  
  8.     string str = HW;  
  9.     cout << str << endl;  
  10. }  
void func1() 
{
#define HW "HelloWorld";
}

void func2()
{
string str = HW;
cout << str << endl;
}



【例2.3.2typedef有自己的作用域

  1. void func1()  
  2. {  
  3.     typedef unsigned int UINT;  
  4. }  
  5.   
  6. void func2()  
  7. {  
  8.     UINT uValue = 5;//error C2065: ‘UINT’ : undeclared identifier  
  9. }  
void func1() 
{
typedef unsigned int UINT;
}

void func2()
{
UINT uValue = 5;//error C2065: 'UINT' : undeclared identifier
}



【例2.3.3

  1. class A  
  2. {  
  3.     typedef unsigned int UINT;  
  4.     UINT valueA;  
  5.     A() : valueA(0){}  
  6. };  
  7.   
  8. class B  
  9. {  
  10.     UINT valueB;  
  11.     //error C2146: syntax error : missing ’;’ before identifier ‘valueB’  
  12.     //error C4430: missing type specifier - int assumed. Note: C++ does not support default-int  
  13. };  
class A 
{
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
};

class B
{
UINT valueB;
//error C2146: syntax error : missing ';' before identifier 'valueB'
//error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
};



上面例子在B類中使用UINT會出錯,因爲UINT只在類A的作用域中。此外,在類中用typedef定義的類型別名還具有相應的訪問權限,【例2.3.4】:

  1. class A  
  2. {  
  3.     typedef unsigned int UINT;  
  4.     UINT valueA;  
  5.     A() : valueA(0){}  
  6. };  
  7.   
  8. void func3()  
  9. {  
  10.     A::UINT i = 1;  
  11.     // error C2248: ‘A::UINT’ : cannot access private typedef declared in class ‘A’  
  12. }  
class A 
{
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
};

void func3()
{
A::UINT i = 1;
// error C2248: 'A::UINT' : cannot access private typedef declared in class 'A'
}



而給UINT加上public訪問權限後,則可編譯通過。

【例2.3.5】:

  1. class A  
  2. {  
  3. public:  
  4.     typedef unsigned int UINT;  
  5.     UINT valueA;  
  6.     A() : valueA(0){}  
  7. };  
  8.   
  9. void func3()  
  10. {  
  11.     A::UINT i = 1;  
  12.     cout << i << endl;  
  13. }  
class A 
{
public:
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
};

void func3()
{
A::UINT i = 1;
cout << i << endl;
}



 

2.4 對指針的操作

二者修飾指針類型時,作用不同。

  1. typedef int  pint;  
  2. #define PINT int   
  3.   
  4. int i1 = 1, i2 = 2;  
  5.   
  6. const pint p1 = &i1;    //p不可更改,p指向的內容可以更改,相當於 int  const p;  
  7. const PINT p2 = &i2;    //p可以更改,p指向的內容不能更改,相當於 const int *p;或 int const *p;  
  8.   
  9. pint s1, s2;    //s1和s2都是int型指針  
  10. PINT s3, s4;    //相當於int  s3,s4;只有一個是指針。  
  11.   
  12. void TestPointer()  
  13. {  
  14.     cout << ”p1:” << p1 << “  p1:” << *p1 << endl;  
  15.     //p1 = &i2; //error C3892: ‘p1’ : you cannot assign to a variable that is const  
  16.     *p1 = 5;  
  17.     cout << ”p1:” << p1 << “  *p1:” << *p1 << endl;  
  18.   
  19.     cout << ”p2:” << p2 << “  *p2:” << *p2 << endl;  
  20.     //*p2 = 10; //error C3892: ‘p2’ : you cannot assign to a variable that is const  
  21.     p2 = &i1;  
  22.     cout << ”p2:” << p2 << “  *p2:” << *p2 << endl;  
  23. }  
typedef int  pint;

define PINT int *

int i1 = 1, i2 = 2;

const pint p1 = &i1; //p不可更改,p指向的內容可以更改,相當於 int * const p;
const PINT p2 = &i2; //p可以更改,p指向的內容不能更改,相當於 const int *p;或 int const *p;

pint s1, s2; //s1和s2都是int型指針
PINT s3, s4; //相當於int * s3,s4;只有一個是指針。

void TestPointer()
{
cout << "p1:" << p1 << " *p1:" << *p1 << endl;
//p1 = &i2; //error C3892: 'p1' : you cannot assign to a variable that is const
*p1 = 5;
cout << "p1:" << p1 << " *p1:" << *p1 << endl;

cout &lt;&lt; "p2:" &lt;&lt; p2 &lt;&lt; "  *p2:" &lt;&lt; *p2 &lt;&lt; endl;
//*p2 = 10; //error C3892: 'p2' : you cannot assign to a variable that is const
p2 = &amp;i1;
cout &lt;&lt; "p2:" &lt;&lt; p2 &lt;&lt; "  *p2:" &lt;&lt; *p2 &lt;&lt; endl;

}

結果:

p1:00EFD094  *p1:1

p1:00EFD094  *p1:5

p2:00EFD098  *p2:2

p2:00EFD094  *p2:5

 

 

參考和引用文章:

關於typedef的用法總結

Typedefdefine的區別


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章