typedef


Typedef
typedefは、プログラミング言語CおよびC ++で予約されているキーワードです。別のデータ型の追加の名前(エイリアス)を作成するために使用されますが、新しい型は作成されません。ただし、typedef修飾子が配列要素に転送される配列型の修飾typedefのあいまいな場合を除きます。タイプ。このように、多くの場合、複雑な宣言のシンタックス単純化するために使用されるデータ構造からなる構造体と組合タイプの、しかしための特定の記述タイプ名を提供しているだけの共通の通りであります さまざまな長さの整数データ型。

コンテンツ
1 構文
2 例
2.1 ドキュメントの使用 2.2 タイプの簡略化 2.3 ポインタ
2.3.1 定数ポインタ
2.4 構造体と構造体ポインタ 2.5 関数ポインタ 2.62.6 配列
3 型キャスト
4 C ++での使用法
4.1 テンプレートで使用する6 使用上の懸念
7 も参照してください
8 参考文献

構文
typedef宣言の構文は次のとおりです。 typedef タイプ宣言;
新しいタイプのエイリアスの名前は、他のC識別子を宣言するのと同じ構文に従うため、より詳細な形式になります。 typedef タイプ定義
識別子
でC標準ライブラリとでPOSIXの仕様のtypedef定義の識別子は、多くの場合、接尾辞れる_tなどのように、size_t型とのtime_t。これは他のコーディングシステムで実践されていますが、POSIXはこの実践をPOSIXデータ型用に明示的に予約しています。


typedef int length ;
これにより、タイプがタイプlengthの同義語として作成されますint。

ドキュメントの使用
typedef宣言は、プログラミングコンテキスト内の変数の意味を示すことにより、ドキュメントとして使用できます。たとえば、測定単位またはカウントの式を含めることができます。一般的な宣言、
int current_speed ; int high_score ; void congratulate (int your_score ){
if (your_score > high_score ){
// … } }
コンテキスト固有のタイプを宣言することで表現できます。
typedef int km_per_hour ; typedef int型ポイント。 // `km_per_hour`はここでは` int`と同義であるため、コンパイラは//新しい変数を整数として扱います。km_per_hour current_speed ; ポイントhigh_score ; void congratulate (points your_score ){
if (your_score > high_score ){
// … } }
コードの両方のセクションは同じように実行されます。ただし、2番目のコードブロックでtypedef宣言を使用すると、2つの変数が同じデータ型を表している一方でint、異なるデータまたは互換性のないデータを格納していることが明確になります。の定義はcongratulate()、(またはとして宣言されていない他の変数)を引数として渡してはならないことをyour_scoreプログラマーに示します。両方がデータ型の変数として宣言されている場合、これはそれほど明白ではありません。ただし、表示はプログラマーのみを対象としています。C / C ++コンパイラは、両方の変数を型であると見なし、以下のコードスニペットの「間違った」引数型の型の不一致の警告またはエラーにフラグを立てません。current_speedpointsintintcongratulate(points your_score)
void foo (){
km_per_hour km100 = 100 ;
おめでとう(km100 );}

タイプの簡略化
typedefは、複合型(struct、union)またはポインター型の宣言を単純化するために使用できます。たとえば、
struct MyStruct { int data1 ; char data2 ; };
これはデータ型を定義しますstruct MyStruct。Cでのこのタイプの変数宣言にもキーワードstructが必要ですが、C ++では省略できます。
struct MyStruct a ;
typedef宣言により、structCで指定する必要がなくなります。たとえば、宣言
typedef struct MyStruct newtype ;
に削減されます:
ニュータイプa ;
構造体宣言とtypedefを組み合わせて1つのステートメントにすることもできます。
typedef struct MyStruct {
int data1 ; char data2 ; } newtype ;
または、次のように使用できます。
typedef struct {
int data1 ; char data2 ; } newtype ;
C ++、C、キーワードとは対照的に、struct、class、及びenum限り別の識別子への曖昧さがないように、定義とは別の変数宣言において任意です。
struct MyStruct x ; MyStruct y ;
そのため、MyStruct使用newtypeできる場所ならどこでも使用できます。ただし、その逆は当てはまりません。たとえば、のコンストラクタメソッドにMyStruct名前を付けることはできませんnewtype。
でも名高い例C ++が必要とstructキーワードがあるPOSIX のstatシステムコールの引数に同じ名前の構造体を使用しています。
int stat (const char * filename 、struct stat * buf )
{{ // … }
ここでは、CとC ++の両方でstructパラメーター定義にキーワードが必要です。

ポインタ
typedefは、新しいポインタ型を定義するために使用できます。
typedef int * intptr ; intptr ptr ; //同じ:// int * ptr;
intptrポインタタイプの新しいエイリアスint *です。定義はintptr ptr;、ptrタイプがint *。の変数を定義します。したがって、ptrは型の変数を指すことができるポインタintです。
typedefを使用して新しいポインタ型を定義すると、混乱を招くことが例えば:
typedef int * intptr ; // ‘cliff’と ‘allen’はどちらもint *型です。intptr崖、アレン; // ‘cliff2’はint *型ですが、 ‘allen2’はint **型です。intptr cliff2 、* allen2 ; //同じ:// intptr cliff2; // intptr * allen2;
上記は、両方の型でintptr cliff, allen;2つの変数を定義することを意味しますint*。これは、typedefで定義された型が型であり、拡張ではないためです。換言すれば、intptrあるint*タイプの両方を飾るcliffとallen。タイプが飾ると。だから、2つの独立した定義に相当し、そして。これは、タイプを持つメモリを指すポインタであることを意味します。すぐに、タイプがintptr cliff2, *allen2;intptrcliff2*allen2intptr cliff2, *allen2;intptr cliff2;intptr *allen2intptr *allen2allen2int*allen2int**

定数ポインタ
繰り返しになりますが、typedefは展開ではなく型を定義するため、const修飾子を使用する宣言は、予期しない、または直感的でない結果をもたらす可能性が次の例では、整数型への定数ポインターを宣言しています。定数整数へのポインタではありません:
typedef int * intptr ; const intptr ptr = NULL ; //同じ:// int * const ptr = NULL;
定数ポインタであるため、宣言で初期化する必要が

構造体と構造体ポインタ
Typedefは、構造体 ポインター型の定義または宣言を単純化することもできます。このことを考慮:
構造体 ノード{ intデータ; struct Node * nextptr ; };
typedefを使用すると、上記のコードを次のように書き直すことができます。
typedefは構造体ノードノード。 構造体 ノード{ intデータ; ノード* nextptr ; };
Cでは、構造体をポインターまたは非ポインターと混合する場合でも、1つのステートメントで同じタイプの複数の変数を宣言できます。ただし、各変数をポインターとして指定するには、各変数の前にアスタリスクを付ける必要が以下では、プログラマーはそれerrptrが実際にであると想定するかもしれませんNode *が、誤植はそれerrptrがであるということを意味しNodeます。これにより、微妙な構文エラーが発生する可能性が
struct Node * startptr 、* endptr 、* curptr 、* prevptr 、errptr 、* refptr ;
typedefを定義することによりNode *、すべての変数が構造体ポインター型であることが保証されます。つまり、各変数が構造体型を指すポインター型であることが保証されます。
typedef struct Node * NodePtr ; NodePtr startptr 、endptr 、curptr 、prevptr 、errptr 、refptr ;

関数ポインタ
int do_math (float arg1 、int arg2 ){
arg2を返す; }int call_a_func (int (* call_this )(float 、int )){
INT出力= call_this (5.5 、7 )。
出力を返す; }int final_result = call_a_func (&do_math );
上記のコードは、typedef仕様で書き直すことができます。
typedef int (* MathFunc )(float 、int ); int do_math (float arg1 、int arg2 ){
arg2を返す; }int call_a_func (MathFunc call_this ){
INT出力= call_this (5.5 、7 )。
出力を返す; }int final_result = call_a_func (&do_math );
ここに、MathFuncタイプの新しいエイリアスがAMathFuncは整数を返す関数へのポインタであり、引数としてfloatの後に整数を取ります。
関数が関数ポインタを返す場合、typedefがないとさらに混乱する可能性が以下は、関数プロトタイプである信号(3)からのFreeBSD。
void (* signal (int sig 、void (* func )(int )))(int );
上記の関数宣言は、関数が引数として受け入れるもの、または関数が返す型を明確に示していないため、不可解です。初心者のプログラマーは、関数intが引数として単一を受け入れて何も返さないと想定することもありますが、実際には、関数ポインターが必要であり、別の関数ポインターを返します。よりきれいに書くことができます:
typedef void (* sighandler_t )(int ); sighandler_tシグナル(int sig 、sighandler_t func );

配列
typedefを使用して、配列型の定義を簡略化することもできます。例えば、
typedef char arrType ; arrType ARR = { 1 、2 、3 、4 、5 、6 }。
arrType * pArr ; //同じ:// char arr = {1、2、3、4、5、6}; // char(* pArr);
ここで、arrTypeのための新たなエイリアスであるchar6つの要素を持つ配列型であるタイプは、。の場合arrType *pArr;、pArrはそのcharタイプのメモリを指すポインタです。

型キャスト
typedefは、型定義構文を使用して作成されますが、型キャスト構文を使用して作成されたかのように使用できます。(型キャストはデータ型を変更します。)たとえば、次の最初の行の後の各行で:
// `funcptr`は、` double`を受け取り `int`を返す関数へのポインタです。typedef int (* funcptr )(double ); // CとC ++の両方で有効です。funcptr x = (funcptr )NULL ; // C ++でのみ有効です。funcptr y = funcptr (NULL ); funcptr z = static_cast < funcptr > (NULL );
funcptr変数を宣言するために左側で使用され、値をキャストするために右側で使用されます。したがって、typedefは、定義構文を型キャスト構文に変換する方法を理解したくないプログラマーが使用できます。
typedefがないと、通常、定義構文とキャスト構文を同じように使用することはできません。例えば:
void * p = NULL ; //これは合法です。int (* x )(double )= (int (* )(double ))p ; //左側は違法です。int (* )(double )y = (int (* )(double ))p ;
//右側は違法です。int (* z )(double )= (int (* p )(double ));

C ++での使用法
C ++では、型名は複雑になる可能性があり、typedefは、型に単純な名前を割り当てるメカニズムを提供します。
std :: vector < std :: pair < std :: string 、int >> values ; 以下のため(のstd ::ベクトル<はstd ::ペア<のstd ::文字列、int型>> :: const_iteratorの私は=の値を。始める)(; I =!値。エンド(); ++ iの)
{{ std ::ペア< std :: string 、int > const &t = * i ;
// … } と typedef std :: pair < std :: string 、int > value_t ; typedef std :: vector < value_t > values_t ; values_t値; 用(values_t :: const_iteratorのI =値。開始)(; I =!値。エンド(); ++ iの)
{{ value_t const &t = * i ;
// … }
C ++ 11usingでは、typedef。の代わりにtypedefを表現する可能性が導入されました。たとえば、上記の2つのtypedefは、同等に次のように記述できます。
使用value_t =のstd ::ペアを<はstd ::文字列、int型> 。 使用values_t = std :: vector < value_t > ;で使用する

C ++ 03は、テンプレート化されたtypedefを提供しません。たとえば、持っているstringpair表しstd::pair種類ごとにT1をすることはできません使用します。<タイプ名 T >typedef std :: pair < std :: string 、T > stringpair < T > ; //機能しません
ただし、のstringpair::type代わりに受け入れる場合はstringpair、他の方法では使用されていないテンプレートクラスまたは構造体内のtypedefを介して目的の結果を達成することができます。<タイプ名 T >クラス stringpair{{プライベート: // `stringpair `のインスタンス化を防ぎます。stringpair (); パブリック: // `stringpair :: type`が` std :: pair `を表すようにします。typedef std :: pair < std :: string 、T > type ;
};//タイプ `std :: pair `の変数を宣言します。stringpair < int > :: type my_pair_of_string_and_int ;
C ++ 11、テンプレートのtypedefが必要次の構文で添加されるusingのではなく、キーワードをtypedefキーワード。(テンプレートエイリアスを参照して)<タイプ名T > 使用して文字列ペア= STD ::ペア<スタンダード::文字列、T > 。 //タイプ `std :: pair `の変数を宣言します。stringpair < int > my_pair_of_string_and_int ;

他の言語
SystemVerilog、typedefがまさにそれはCやC ++でするように動作します。
Haskell、Miranda、OCamlなどの多くの静的に型付けされた関数型言語では、Cのtypedefと同じ型の同義語を定義できます。Haskellの例:
タイプ PairOfInts = (Int 、 Int )
この例では、型の同義語PairOfIntsを整数型として定義しています。
でSeed7定数型の定義は、型のシノニムを導入するために使用されます。
constタイプ:myVectorは配列整数です。
でスウィフト、一つは使用typealiasのtypedefを作成するためのキーワードを:
typealias PairOfInts = (Int 、 Int )
C#には、typedefまたはusingC ++の構文に類似した機能が含まれています。
newType = global :: Systemを使用します。ランタイム。相互運用。元帥; otherType = Enumsを使用し ます。MyEnumType ; StringListMap = Systemを使用します。コレクション。ジェネリック。辞書<文字列、システム。コレクション。ジェネリック。リスト<文字列>>;
でDキーワードaliasはタイプまたは部分型シノニムを作成することができます。
struct Foo (T ){}エイリアス FooInt = Foo !int ; エイリアス Fun = int デリゲート(int );

使用上の懸念
KernighanとRitchieは、typedefを使用する2つの理由を述べました。第一に、プログラムをよりポータブルにしたり、保守しやすくしたりする手段を提供します。プログラムのソースファイル全体ですべての外観で型を変更する必要はなく、1つのtypedefステートメントのみを変更する必要がのsize_tとptrdiff_tは、そのようなtypedef名です。次に、typedefを使用すると、複雑な定義や宣言を理解しやすくなります。
一部のプログラマーは、typedefの広範な使用に反対しています。ほとんどの議論は、typedefが変数の実際のデータ型を単に隠すという考えに集中しています。たとえば、Linuxカーネルのハッカー兼ドキュメンタリーであるGreg Kroah-Hartmanは、関数プロトタイプ宣言以外の用途には使用しないようにしています。彼は、この慣行はコードを不必要に曖昧にするだけでなく、プログラマーが大きな構造を単純な型であると誤用する可能性もあると主張しています。

も参照してください
抽象データ型
C構文

参考文献
^ Kernighan、Brian W .; リッチー、デニスM.(1988)。Cプログラミング言語(第2版)。ニュージャージー州イングルウッドクリフ:プレンティスホール。NS。 147。ISBN 0-13-110362-8。検索された18年6月2016。Cは、新しいデータ型名を作成するためのtypedefと呼ばれる機能を提供します。…typedef宣言は、いかなる意味でも新しい型を作成しないことを強調する必要が既存のタイプに新しい名前を追加するだけです。
^ 「const型修飾子」。cppreference.com 。
^ 「typedef指定子」。cppreference.com 。検索された18年6月2016。
^ itel、Paul J。; Deitel、HM(2007)。Cプログラミング方法(第5版)。ニュージャージー州アッパーサドルリバー:ピアソンプレンティスホール。ISBN  9780132404167。取得した12年9月2012。構造体型の名前は、短い型名を作成するためにtypedefで定義されることがよく ^ “タイプエイリアス、エイリアステンプレート(C ++ 11以降)-cppreference.com”。en.cppreference.com 。
^ タラ、ディーパッククマール。「SystemVerilogデータ型Part-V」。www.asic-world.com。ASICワールド。
^ http://msdn.microsoft.com/en-us/library/aa664765(VS.71).aspx ^ 「宣言-Dプログラミング言語」。dlang.org 。
^ Kroah-Hartman、Greg(2002-07-01)。「適切なLinuxカーネルコーディングスタイル」。LinuxJournal。typedefを使用すると、変数の実際の型のみが非表示になります。