2011-02-07 17 views
5
Objective-CのIDで

がtypedefである:Objective-C; typedef objc_objectはポインタのないidの代わりに使用します。

typedef struct objc_object { 
    Class isa; 
} *id; 

だから宣言(および初期化)することができる可変例えばこのように:

// using id 
id po_one = @"one"; 

コンパイルは正常です。だから、

typedef struct objc_object O; 

変数:

私は自分のスキームで私のタイプに名前を付けているので、私はこのように(オブジェクトのOと)自分のtypedefを追加したいのtypedef私はIDで暗黙のポインタを嫌うので、

初期化Iから:これは警告でコンパイル

// using O 
O * po_two = @"two"; 

:(初期化付き)の宣言は次のようになります再び罰金コンパイル

// using struct objc_object 
struct objc_object * po_three = @"three"; 

:ncompatibleポインタ タイプ

は、私の知る限りのtypedefを理解するように私は、後者がと同等であるべきと考えました。

po_two = po_one; 
po_two = po_three; 

両方が警告なしにコンパイル:

それは驚くべきことです。

だから私は試してみました:

typedef struct objc_object * PO; 

私はポインタ(私は避けたい正確なものであること - これだけのテストの理由で)が含まれている場合、それは警告なしに動作するかどうかを確認するための外のtypedefかどうかを確認します構造体定義は構造体定義のtypedef(この場合はidの定義)とは異なる働きをします。

// using PO 
PO po_four = @"four"; 

これもうまくいきます。

私が使用している場合:

#define O struct objc_object 

Oを使用して構築物は再び警告なしにコンパイルします。

しかし、できる限り定義の代わりにtypedefを使用する方が好きです。

私は困惑しています。 typedefに関する私の誤解は何ですか?

+0

どのコンパイラ? – JeremyP

+1

また、 'O *'の代わりに 'NSObject *'を使うこともできます。 'NSObject * po_two = @" two ";'、ほとんどの場合です。 –

答えて

2

私はコンパイラの専門家ではないので、おそらく本当のエキスパートがあなたに良い答えを与えることができます。いずれにしても、私の知識に基づいて、コンパイラは型チェックを行うときに、このチェックをすべての可能なデータ型構造の一種のテーブルを生成する "解析木"に基づいて行い、2つの定義が同じ行テーブルにしたがって、このテーブルからシンボルと型定義を取り出して比較することで動作します。 "struct objc_object"は、これらのデータ構造の1つです。次に、idが定義されると、別のエントリ、 "id - > struct objc_object *"を生成します。 po_threeの定義は、同じ参照: "struct objc_object *"(infact "="が優先順位が最も低い)につながります。 同じことがpo_fourにも起こります。なぜなら、POは定義によって同じ参照につながるからです(PO - > struct objc_object *)。 #defineで定義を使用すると、前処理のおかげで、まだ "struct objc_object *"を参照しています。 しかし、

O * po_two = @"two"
を使用すると、実際には "id"(@ "two")、つまり "struct objc_object *"と "struct objc_object"へのポインタである1つのタイプを照合しようとしています。論理的には同じですが、テーブル内の同じ参照につながりません。その理由は、 "O"型がまだ定義されていないため、po_twoは単に "O"および "O - > struct objc_object"へのポインタとしてシンボルテーブルに格納されるためです。これが警告の理由です。po_twoは@ "two"とは別のものへのポインタです。

私は好奇心があります: "nm"を使ってシンボルテーブルをプロットしようとしましたか?

+0

テーブルエントリが一致していないと推測できます。 私はnmを試しましたが、有用な情報はありません。 また、デバッガは少なくとも初期化後には同じタイプを表示します。 現時点では、gccに組み込まれたハックがあり、ポインタをidにキャストできるようになっています。しかし、たぶん彼らは普通のc型のルール(idとO *に相当する型につながるはずです)を考えるのを忘れたので、typedefは警告を出します。 – carpetemporem

+0

はい、これは、po_two = po_threeの欠落している警告を説明します。 – viggio24

関連する問題