typedefと#defineの違い
5218 ワード
1. typedef
typedef故名思意はタイプ定義の意味であるが、新しいタイプを定義するのではなく、既存のタイプに別名を付ける点では、参照の意味と同様に、参照は変数またはオブジェクトの別名であり、typedefはタイプの別名を定義する.typedefの役割は主に2つあります.
1.1複雑なタイプ宣言の簡略化
複雑なタイプ宣言を簡略化したり、既存のタイプに明確な別名を付けたりします.次のようになります.
typedef bool (*FuncPointer)(int, double);//boolタイプを返し、2つの(intとdouble)パラメータを持つ関数を返すポインタタイプFuncPointerを宣言します.
FuncPointer pFunc;//FuncPointerタイプの関数ポインタオブジェクトpFuncを宣言
1.2プラットフォームに関係のないタイプを定義する
プラットフォームに関係のないタイプを定義し、異なるプラットフォームのタイプの差異化を遮断する.次のようになります.
typedefを使用して、プラットフォームに関係のないタイプを定義します.
例えばREALという浮動小数点のタイプを定義し、目標プラットフォームにおいて、最高精度を表すタイプは以下の通りである.
typedef long double REAL;
long doubleをサポートしていないプラットフォーム2で、次のように変更します.
typedef double REAL;
doubleもサポートされていないプラットフォーム3で、次のように変更されました.
typedef float REAL;
すなわち、プラットフォームをまたぐ場合、typedef自体を変更すればよく、他のソースコードを変更する必要はありません.
標準ライブラリではsize_など、このテクニックが広く使われています.t.またtypedefは、単純な文字列置換ではなく、タイプを定義した新しい別名であるため、マクロよりも安定している.
1.3 structとの併用
C++では、structはclassと同じ役割を果たします.デフォルトのアクセス権が異なり、structはpublic、classはprivateがデフォルトです.
【例1.3.1】:
StructのタイプPersonを定義し、Personのオブジェクトpersonを定義します.
または
StructのタイプPersonを定義し、定義と同時にPersonのオブジェクトpersonも宣言します.
しかしC言語ではstructの定義と宣言はtypedefを用いる.
【例1.3.2】:
typedefがなければstruct Person personを使わなければなりません.次のように宣言します.
【例1.3.3】
または
2.typedefと#defineの違い
2.1.実行時間が異なる
キーワードtypedefはコンパイルフェーズで有効であり、コンパイルフェーズであるため、typedefにはタイプチェックの機能がある.
#defineはマクロ定義であり、前処理フェーズ、すなわちコンパイルの前に発生し、検査を行わずに単純で機械的な文字列置換のみを行う.
【例2.1.1】typedefは対応するタイプの検査を行う:
【例2.1.2】#defineタイプチェックをしない:
プログラムの出力結果は:36であり、根本的な原因は#defineが単純な文字列置換であることにある.
2.2.機能に違いがある
typedefは、タイプの別名を定義したり、プラットフォームに関係のないデータ型を定義したり、structとの結合使用などに使用します.
#defineは、タイプに別名を付けるだけでなく、定数、変数、コンパイルスイッチなどを定義することもできます.
2.3.役割ドメインが違う
#defineは、役割ドメインの制限はありません.以前に定義されたマクロであれば、以降のプログラムで使用できます.
typedefには独自の役割ドメインがあります.
【例2.3.1】役割ドメインの制限はなく、先に定義されていればよい
【例2.3.2】typedefには独自の役割ドメインがある
【例2.3.3】
上記の例では、クラスAの役割ドメインにのみ存在するため、BクラスでUINTを使用するとエラーが発生します.また、クラスでtypedefで定義されたタイプ別名には、対応するアクセス権限もあります.【例2.3.4】
UINTにpublicアクセス権を付与するとコンパイルできます.
【例2.3.5】:
2.4.ポインタの操作
両者がポインタタイプを修飾する場合、作用は異なります.
結果:
p1:00EFD094 *p1:1
p1:00EFD094 *p1:5
p2:00EFD098 *p2:2
p2:00EFD094 *p2:5
記事の参照と参照:
『typedefの使い方についてのまとめ』
『Typedefとdefineの違い』
typedef故名思意はタイプ定義の意味であるが、新しいタイプを定義するのではなく、既存のタイプに別名を付ける点では、参照の意味と同様に、参照は変数またはオブジェクトの別名であり、typedefはタイプの別名を定義する.typedefの役割は主に2つあります.
1.1複雑なタイプ宣言の簡略化
複雑なタイプ宣言を簡略化したり、既存のタイプに明確な別名を付けたりします.次のようになります.
typedef bool (*FuncPointer)(int, double);//boolタイプを返し、2つの(intとdouble)パラメータを持つ関数を返すポインタタイプFuncPointerを宣言します.
FuncPointer pFunc;//FuncPointerタイプの関数ポインタオブジェクトpFuncを宣言
1.2プラットフォームに関係のないタイプを定義する
プラットフォームに関係のないタイプを定義し、異なるプラットフォームのタイプの差異化を遮断する.次のようになります.
typedefを使用して、プラットフォームに関係のないタイプを定義します.
例えばREALという浮動小数点のタイプを定義し、目標プラットフォームにおいて、最高精度を表すタイプは以下の通りである.
typedef long double REAL;
long doubleをサポートしていないプラットフォーム2で、次のように変更します.
typedef double REAL;
doubleもサポートされていないプラットフォーム3で、次のように変更されました.
typedef float REAL;
すなわち、プラットフォームをまたぐ場合、typedef自体を変更すればよく、他のソースコードを変更する必要はありません.
標準ライブラリではsize_など、このテクニックが広く使われています.t.またtypedefは、単純な文字列置換ではなく、タイプを定義した新しい別名であるため、マクロよりも安定している.
1.3 structとの併用
C++では、structはclassと同じ役割を果たします.デフォルトのアクセス権が異なり、structはpublic、classはprivateがデフォルトです.
【例1.3.1】:
struct Person
{
string name;
int age;
float height;
};
Person person;
StructのタイプPersonを定義し、Personのオブジェクトpersonを定義します.
または
struct Person
{
string name;
int age;
float height;
}person;
StructのタイプPersonを定義し、定義と同時にPersonのオブジェクトpersonも宣言します.
しかしC言語ではstructの定義と宣言はtypedefを用いる.
【例1.3.2】:
typedef struct __Person
{
string name;
int age;
float height;
}Person; // Person
Person person;
typedefがなければstruct Person personを使わなければなりません.次のように宣言します.
【例1.3.3】
struct Person
{
string name;
int age;
float height;
};
struct Person person;
または
struct Person
{
string name;
int age;
float height;
}person; //person Person
2.typedefと#defineの違い
2.1.実行時間が異なる
キーワードtypedefはコンパイルフェーズで有効であり、コンパイルフェーズであるため、typedefにはタイプチェックの機能がある.
#defineはマクロ定義であり、前処理フェーズ、すなわちコンパイルの前に発生し、検査を行わずに単純で機械的な文字列置換のみを行う.
【例2.1.1】typedefは対応するタイプの検査を行う:
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タイプチェックをしない:
//#define :
#define f(x) x*x
int main()
{
int a=6, b=2, c;
c=f(a) / f(b);
printf("%d
", c);
return 0;
}
プログラムの出力結果は:36であり、根本的な原因は#defineが単純な文字列置換であることにある.
2.2.機能に違いがある
typedefは、タイプの別名を定義したり、プラットフォームに関係のないデータ型を定義したり、structとの結合使用などに使用します.
#defineは、タイプに別名を付けるだけでなく、定数、変数、コンパイルスイッチなどを定義することもできます.
2.3.役割ドメインが違う
#defineは、役割ドメインの制限はありません.以前に定義されたマクロであれば、以降のプログラムで使用できます.
typedefには独自の役割ドメインがあります.
【例2.3.1】役割ドメインの制限はなく、先に定義されていればよい
void func1()
{
#define HW "HelloWorld";
}
void func2()
{
string str = HW;
cout << str << endl;
}
【例2.3.2】typedefには独自の役割ドメインがある
void func1()
{
typedef unsigned int UINT;
}
void func2()
{
UINT uValue = 5;//error C2065: 'UINT' : undeclared identifier
}
【例2.3.3】
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
};
上記の例では、クラスAの役割ドメインにのみ存在するため、BクラスでUINTを使用するとエラーが発生します.また、クラスでtypedefで定義されたタイプ別名には、対応するアクセス権限もあります.【例2.3.4】
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】:
class A
{
public:
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
};
void func3()
{
A::UINT i = 1;
cout << i << endl;
}
2.4.ポインタの操作
両者がポインタタイプを修飾する場合、作用は異なります.
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 << "p2:" << p2 << " *p2:" << *p2 << endl;
//*p2 = 10; //error C3892: 'p2' : you cannot assign to a variable that is const
p2 = &i1;
cout << "p2:" << p2 << " *p2:" << *p2 << endl;
}
結果:
p1:00EFD094 *p1:1
p1:00EFD094 *p1:5
p2:00EFD098 *p2:2
p2:00EFD094 *p2:5
記事の参照と参照:
『typedefの使い方についてのまとめ』
『Typedefとdefineの違い』