typedefに関する知識

12651 ワード

typedefに関する知識:
typedefは、プログラミング言語で複雑な宣言に簡単な別名を定義するために使用され、マクロ定義とは少し異なります.
それ自体はクラスを格納するキーワードであり、auto、extern、mutable、static、registerなどのキーワードと同じ式には表示されません.
typedefはC言語のキーワードであり、データ型の新しい名前を定義する役割を果たす.ここでのデータ型には、内部データ型(int,charなど)やカスタムデータ型(structなど)が含まれる.
プログラミングでtypedefを使用する目的は一般的に2つあり、1つは変数に覚えやすく意味の明確な新しい名前を与えることであり、もう1つは比較的複雑なタイプ宣言を簡略化することである.
基本的な使い方:
1、typedefの最も簡単な使用
//       long     , byte_4。
typedef long byte_4;

2、typedefと構造体(struct)を組み合わせて使用する
typedef struct tagMyStruct
{
     
	int iNum; 
	long lLength;
}MyStruct;

この文は実際に2つの操作を完了しました:2.1)新しい構造タイプを定義します.
struct tagMyStruct
{
     
	int iNum;
	long lLength;
};

分析:tag MyStructは「tag」、すなわち「ラベル」と呼ばれ、実際には一時的な名前であり、structキーワードはtag MyStructとともに、typedefがあるかどうかにかかわらず、この構造タイプを構成している.struct tagMyStruct varNameで変数を定義できますが、structとtagMyStructを合わせて構造タイプを表すことができるため、tagMyStruct varNameを使用して変数を定義するのは間違っています.2.2)typedefはこの新しい構造にMyStructという名前をつけた.typedef struct tagMyStruct MyStruct; したがって、MyStructは実際にstruct tagMyStructに相当し、MyStruct varNameを使用して変数を定義することができます.
3.typedefと#defineの問題
//       pStr       ,       ?       ?
typedef char* pStr;

#define pStr char*

答えと分析:通常typedefは#defineよりよく、特にポインタがある場合です.例を見てください:typedef char*pStr 1;#define pStr2 char*
pStr1 s1,s2; pStr2 s3,s4; 上記の変数定義では、s 1、s 2、s 3はchar*として定義されていますが、s 4はcharとして定義されており、私たちが予想したポインタ変数ではありません.根本的な原因は、#defineは単純な文字列置換であり、typedefは1つのタイプに新しい名前を付けることです.前例のdefine文はpStr 2 s 3,*s 4と書かなければならない.これで正常に実行できます.
#defineの使用例:
#include 
#define f(x) x*x
int main(void)
{
     
    int a=6, b=2, c;
    c = f(a) / f(b);
    printf("%d
"
, c); return 0; }

以下のプログラムの出力結果は:36です.そのため、多くのC言語プログラミング仕様で#define定義の使用について言及されている場合、定義に式が含まれている場合はカッコを使用する必要があります.上記の定義は、#define f(x)(x)*(x))もちろんtypedefを使用する場合は、このような問題はありません.
4.typedefと#defineの別の例
//               ,           ?
typedef char *pStr;
char string[4]="abc";
const char *p1=string;
const pStr p2=string;
p1++;
p2++;

答えと分析:p 2++が間違っています.この問題は、typedefは#defineとは異なり、簡単なテキスト置換ではありません.上記のコードのconst pStr p 2はconst char*p 2に等しくありません.const pStr p 2とpStr const p 2は本質的に区別されず、変数を読み取り専用に制限しているが、ここで変数p 2のデータ型はシステム固有のタイプではなく、私たち自身が定義したものである.したがって、const pStr p 2は、char*のデータ型を規定する変数p 2が読み取り専用であるため、p 2++エラーを意味する
5.defineとtypedefの引用5.1)#defineマクロ定義には、#ifdef、#ifndefなどを用いて論理判断を行うことができ、#undefを用いて定義を取り消すこともできるという特別な利点がある.一般ヘッダファイルの定義:aa.h
#ifndef _AA_H_
#define _AA_H_
    //               
    int func_xx(int);
#endif

5.2)typedefにも特別な長所がある:それは範囲規則に合致し、typedefで定義された変数タイプを使用してその作用範囲は定義された関数またはファイル内(この変数で定義された位置に依存)に制限され、マクロ定義にはこのような特性はない.
6.typedefと複雑な変数宣言は複雑な宣言が利用できる「右左の法則」を理解する:変数名から見て、まず右に行って、それから左に行って、括弧にぶつかって読む方向を変える;括弧内の分析が完了すると括弧から飛び出すか、右から左の順序で分析が完了するまでループします.例:int(func)(int p);まず変数名funcを見つけます.外には括弧があり、左側には番号があります.これはfuncがポインタであることを示しています.それからこのカッコを飛び出して、まず右を見て、またカッコ(関数の後ろにのみ形参カッコが付いている)に出会った.これは関数であることを示しているので、funcはこのような関数を指すポインタ、すなわち関数ポインタであり、このような関数はintタイプのパラメータを持ち、戻り値タイプはintであり、ここでは宣言関数である.    int (func[5])(int ); funcの右側には[]演算子があり、funcが5つの要素を持つ配列であることを示します.funcの左側に1つ、説明funcの要素はポインタ(ここではfuncを修飾するのではなくfuncを修飾することに注意[5]である.なぜなら[]演算子の優先度比が高く、funcが[]と結合しているからである.このカッコを飛び出して右を見ると、またカッコに遭遇し、func配列の要素が関数タイプのポインタであることを説明し、その指す関数はint*タイプのパラメータを有し、戻り値タイプはintである.
2つのパターンを覚えることもできます:type()(...)関数ポインタtype()[]配列ポインタ
複雑な変数に対してタイプ別名を作成する方法は簡単です.従来の変数宣言式で変数名の代わりにタイプ名を使用し、キーワードtypedefを文の先頭に追加すればいいです.
1:int *(a[5])(int, char);//pFunは私たちが建てたタイプの別名typedef int(pFun)(int,char);//定義された新しいタイプを使用してオブジェクトを宣言し、int(a[5])(int,char)に等しい.pFun a[5];
上記のtypedef動作は、同義語の代わりに実際のタイプのdefineマクロに似ています.異なる点はtypedefがコンパイル時に解釈されるため、コンパイラにプリプロセッサの能力を超えたテキスト置換に対処させることである.defineは、前処理時に置き換えられます.
重点を置く
typedef int (*PF) (const char *, const char *); この宣言は、2つのconst char*タイプのパラメータとintタイプの戻り値を持つ関数ポインタの同義語としてPFタイプを導入した.
ソースファイル:a.c
//        
typedef int (*FUNC_TYPE)(char *);//    FUNC_TYPE

//      (func_zz b.c)
extern int func_zz( FUNC_TYPE func, char * );

//      
int  func_xx(  char *aa ){
     
	//        
	printf("echo:%s
"
, aa ); return 0; } int main(){ char str1[100]={ 0}; strcpy(str, "xxx"); //func_zz ;func_xx func_zz( func_xx, str1 ); exit (0); }

ソースファイル:b.c
//        FUNC_TYPE,    
//*      
typedef int (*FUNC_TYPE)( char *, );

//      
int func_zz( FUNC_TYPE func, char *str1 ){
     
	
	//     ,    func    
	func(str1);

	return 0;
}


まとめ:1.メインプログラムではコールバック関数タイプtypedef int(*FUNC_TYPE)を定義する必要があります.タイプ名:FUNC_TYPE 2.メインプログラムでは、登録関数を宣言する必要があります(externは変数または関数の前に置くことができ、変数または関数の定義が別のファイルにあることを示します.プロンプトコンパイラがこの変数または関数に遭遇した場合、他のモジュールで定義を探します).extern int func_zz(FUNC_TYPE func,char*);3.関数が登録されているファイルでは、コールバック関数タイプtypedef int(*FUNC_TYPE)を定義する必要があります.タイプ名:FUNC_TYPE