2011-02-27 36 views
5

以下の定義ABによってを交換する:#defineとtypedefオペランドが逆になるのはなぜですか?

#define A B 

をこのタイプBの別名であることAを定義するのに対し:

typedef B A; 

なぜ?これはインコヒーレントではないですか?

+0

PS:私は彼らが全く違っていて、非常に異なる目的のために使用されていることを知っています。しかし、個人的には、typedefは別の方法であったはずです。 – fouronnes

+1

それがどんな慰めでもあれば、Ken Thompsonは同じことを考えています。 Goでは、型エイリアスだけを生成する 'typedef'に直接相当するものはありませんが、古い型から新しい型を作成する方法は' type NewType OldType'です。彼とDennis Ritchieが、Goが明示的に類似しているという構文の決定をCとは一線を画して議論するのだろうかと思います.Goの宣言の順序は基本的に「逆の方法」です:-) –

答えて

7

簡単に言えば、次の変数宣言を考えてみます。

// declare a variable called "myInt" with type int 
int myInt; 
// declare a variable called "myDouble" with type double 
double myDouble; 
// declare a variable called "myLong" with type long 
long myLong; 
// declare a variable called "myFunc" with type pointer to function 
void (*myFunc)(char*); 

その後typedef sは完璧な理にかなって:

// declare a type alias called "myInt" with type int 
typedef int myInt; 
// declare a type alias called "myDouble" with type double 
typedef double myDouble; 
// declare a type alias called "myLong" with type long 
typedef long myLong; 
// declare a type alias called "myFunc" with type pointer to function 
typedef void (*myFunc)(char*); 

マクロ、一方、関数スタイルの構文を取ることができます:

#define A(B, C) B, C 

A(1, 2) // expands out to 1, 2 

マクロの場合、「名前」の後に続く「定義」makもっと意味がある。

(これはところで、あまりにもC++にも適用されます。)

2

Atypedef)は、複数の記号、たとえば、 typedef int Integer, *PInteger;。 これは変数の定義方法(int var, *pvar;)と一貫しています。

0

はい、typedefの構文は、私も少し捨ててしまう傾向があります。私はあなたの質問が苦情の多くであると仮定します.Cは40歳近くですが、typedefの構文が変わるとは思わないでしょうか?

+0

もちろんnot = D – fouronnes

4

はい、マクロはかなり混乱しています。

typedef言語の残りのほとんどが完了した後、かなりの間、言語に追加されました。これは、ストレージ・クラスと同じシンタックスを使用し:

static int x; 
extern int y; 
typedef int z; 

これらxyzすべてintものとして定義 - エイリアスのために基本的に差がxyタイプintのオブジェクトであるということである、とzintそれ自身。

このように、typedefは適切な言語で適切に適合し、実際には「奇妙な人」のプリプロセッサです(通常通り)。同時に、言語の残りの部分も同様に変わるべきだと主張することができます。それは些細な例については、違いの多くを作るわけではありませんが、私はあなたがより多くを扱う場合は特に、これは読むためにかなり単純だと思う

type 
    z = integer; 

var 
    x : integer; 

:ちょうど明白な例のために、パスカルは、およそ物事の順序を逆転させました複雑な宣言。しかし、Pascalは(ほとんど)好意を失い、Javaのような新しい言語はC構文のこの特定の部分を保持しています(つまり、C言語の部分は変更の必要性が最も高い部分です) 。

+0

+1:宣言を宣言するキーワードの概念を覚えておくとよいでしょう。キーワード/演算子を使わずに、構文的順序だけで呼び出される言語構成を導入する前に、常に2回考えてください。 – Potatoswatter

+0

なぜマクロ(Cプリプロセッサを暗示している)が混乱していると思いますか?それはC言語と比べていくつかの面で全く異なっていますか?絶対に(例えば、早期結合と比較して後期結合)。完全に学ぶのは難しいでしょうか?はい、できます。しかし、混乱ですか?私には分かりません。だからあなたは "混乱"の意味を詳しく説明することができますか? – hlovdal

+0

@hlovdal:最も顕著な問題のいくつかは、1)スコープの欠如、2)デバッガに利用できない情報、3)非常にエラーが発生しやすい(例えば、複数の評価された引数)などです。彼らは*まれに*利用可能な最高のソリューションです。 –

2

Typedefは、storage class specifierグループの言語構文の観点から、externstatic(*)と一緒に使用されているため、typedefの配置は同じです。それは明らかにこのグループに属していませんが、私はそれがおそらく最も誤って配置されていない場所だったと思います。

(*) ストレージクラスにもautoregisterが含まれていますが、それ以上使用するものはありません。

1

なぜ私は言語の意思決定に関係するのか分かりませんが、typedefは私にとって意味があります。

typedef指定子は言語の一部です。タイプをある種の名前にエイリアスする方法として役立ちます。変数の宣言で型が何であるかは、常にインライン展開できます。 typedefミラーの代わりに型に変数を宣言するの、あなたがタイプの名前を宣言している除いて、この使用を使用して

struct arr { int len; char *chars; } name; 
struct arr another_name; 

。それは言語が特定の構造を表し、それを宣言するより自然な方法を使用することができる方法にバインドされていないので

typedef struct { int len; char *chars; } arr; 
arr name; 
arr another_name; 

#defineディレクティブは、プリプロセッサのではなく、言語の一部です。

1

プリプロセッサとコンパイラは実際には独自の構文を持つ2つの異なるプログラムであるためです。プリプロセッサと他の言語とをあまり混乱させないで組み合わせることができました(実際には、dBase IIIプログラムとAutoLISPでcppを使用していました。 他の人が既に指摘したように、typedefはCの宣言システムの構文に従い、#defineは簡単な直進宣言である。

関連する問題