回答:
番号。
#define
プリプロセッサトークンです。コンパイラ自体には決して表示されません。
typedef
コンパイラトークンです。プリプロセッサはそれを気にしません。
どちらを使用しても同じ効果が得られますが、ニーズに応じて適切なものを使用することをお勧めします
#define MY_TYPE int
typedef int My_Type;
物事が「毛むくじゃら」になったら、適切なツールを使用してそれを正しくする
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
void fx_def(void (*)(int) fx);
; 正しい宣言はvoid fx_def(void (*fx)(int));
です。
#define FX_TYPE(f) void (*f)(int)
。:あなたはその後、としてあなたの関数を宣言するだろうvoid fx_def(FX_TYPE(fx));
typedef
変数と同じようにスコープ規則に従いますdefine
が、コンパイル単位の最後まで(または一致するまでundef
)有効です。
また、いくつかのものがで行うことができますtypedef
で行うことができませんdefine
。
例えば:
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
いいえ、同じではありません。例えば:
#define INTPTR int*
...
INTPTR a, b;
前処理後、その行は次のように拡張されます
int* a, b;
うまくいけば、あなたは問題を見るでしょう。a
タイプのみになりますint *
。b
はプレーンとして宣言されますint
(*
型指定子ではなく、宣言子に関連付けられているため)。
それと対照的に
typedef int *INTPTR;
...
INTPTR a, b;
この場合、a
およびb
はtypeになりint *
ます。
関数や配列へのポインタなど、プリプロセッサマクロでエミュレートできないtypedefのクラス全体があります。
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
プリプロセッサマクロでそれを実行してみてください。
#defineはマクロを定義します。
typedefはタイプを定義します。
さて、ここでいくつかの違いがあります:
#defineあなたは、コンパイル時に使用できる定数を定義することができます。定数を#ifdefと共に使用して、コードのコンパイル方法を確認し、コンパイルパラメータに従って特定のコードを特殊化できます。#defineを
使用して、ミニチュアの検索および置換マクロ関数を宣言することもできます。
typedefは、型にエイリアスを与えるために使用できます(おそらく#defineでも行うことができます)が、#define定数の検索と置換の性質により、より安全です。
さらに、typedefで前方宣言を使用すると、使用する型を宣言できますが、書き込み中のファイルにはまだリンクされていません。
プリプロセッサマクロ(「#define
」)は、「検索と置換」の字句置換ツールです。それらはプログラミング言語に完全にとらわれず、何をしようとしているのか理解していません。あなたはそれらを美化したコピー/貼り付けの仕組みと考えることができます-時々それは便利ですが、注意して使用する必要があります。
Typedefは、型のエイリアスを作成できるC言語の機能です。これは、複雑な複合型(構造体や関数ポインターなど)を読みやすく扱いやすいものにするのに非常に役立ちます(C ++では、型をtypedefする必要がある場合さえあります)。
(3)の場合:可能であれば、常にプリプロセッサマクロよりも言語機能を優先する必要があります。したがって、型には常にtypedefを使用し、定数には定数値を使用してください。このようにして、コンパイラーは実際に有意義に対話できます。コンパイラは友だちであることを忘れないでください。そのため、できるだけ多く伝える必要があります。プリプロセッサマクロはによって正反対のことを隠して、コンパイラから、あなたのセマンティクスを。
それらは非常に異なりますが、カスタムデータ型を実装するためによく使用されます(これは、この質問がすべてであると想定しているものです)。
pmgが言及した#define
ように、コンパイラーがコードを認識する前にプリプロセッサーによって(カットアンドペースト操作のように)処理typedef
され、コンパイラーによって解釈されます。
(少なくともデータ型の定義に関して)主な違いの1つは、typedef
より具体的な型チェックが可能になることです。例えば、
#define defType int
typedef int tdType
defType x;
tdType y;
ここで、コンパイラーは変数xをintと見なしますが、変数yはたまたまintと同じサイズの 'tdType'と呼ばれるデータ型と見なします。タイプdefTypeのパラメーターを取る関数を作成した場合、呼び出し元は通常のintを渡すことができ、コンパイラーは違いを認識できません。関数が代わりにtdType型のパラメーターを取った場合、コンパイラーは、関数呼び出し中に適切な型の変数が使用されるようにします。
また、一部のデバッガーはを処理する機能を備えています。これは、typedef
すべてのカスタムタイプを基本プリミティブタイプとしてリストするよりもはるかに便利です(#define
代わりにを使用した場合と同様)。
いいえ
。typedefは、型のエイリアスを作成するCキーワードです。
#defineはプリプロセッサ命令であり、コンパイル前にテキスト置換イベントを作成します。コンパイラがコードに到達すると、元の "#defined"ワードは存在しなくなります。#defineは主にマクロとグローバル定数に使用されます。
上記のように、#define
とtypedefの間には重要な違いがあります。これについて考える正しい方法は、typedefを完全な「カプセル化された」型であると見なすことです。宣言した後は追加できません。
マクロの型名は他の型指定子で拡張できますが、typedefされた型名は拡張できません。
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
また、typedefされた名前は、宣言内のすべてのデクレーターのタイプを提供します。
#define fruit int *
fruit apple, banana;
マクロ展開後、2行目は次のようになります。
int *apple, banana;
Appleはintへのポインタですが、バナナはintです。比較において。次のようなtypedef:
typedef char *fruit;
fruit apple, banana;
リンゴとバナナの両方が同じであると宣言します。前面の名前は異なりますが、どちらもcharへのポインターです。
stdfx
その型の有効なオブジェクトは、intを受け取り、値を返さない関数へのポインターです。