Objective-C;typedef objc_object вместо идентификатора без указателя; - PullRequest
5 голосов
/ 07 февраля 2011

В Objective-C id является typedef:

typedef struct objc_object {
     Class isa;
} *id;

Так что я могу объявить (и инициализировать) переменную, например, так:

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

Компилируется нормально.

Поскольку я называю свои типы в собственной схеме, и так как мне не нравится подразумеваемый указатель в идентификаторе typedef, я хочу добавить собственный typedef (с O для объекта), например так:

typedef struct objc_object O;

Так чтоОбъявление переменной (с инициализацией) может выглядеть следующим образом:

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

Это компилируется с предупреждением:

Инициализация из несовместимого типа указателя

Насколько далекокак я понимаю typedefs, я подумал, что последнее должно быть эквивалентно:

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

, что снова прекрасно компилируется.

Удивительно, что:

po_two = po_one;
po_two = po_three;

оба компилируются безПредупреждения.

Поэтому я попытался:

typedef struct objc_object * PO;

, чтобы увидеть, работает ли он без предупреждения, если я включу указатель (это именно то, чего я хочу избежать - так, просто из соображений теста), чтобыпосмотрите, отличаются ли определения типа вне определения структурыПривязка к typedef в определении структуры (в данном случае это определение id).

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

Это также отлично работает.

Если я использую:

#define O struct objc_object

конструкция с использованием O снова компилируется без предупреждения.

Но я предпочитаю использовать typedefs вместо определений, когда это возможно.

Я озадачен.В чем мое недопонимание с typedefs?

1 Ответ

2 голосов
/ 07 февраля 2011

Я не эксперт по компиляторам, поэтому, вероятно, настоящий эксперт может дать вам лучший ответ.В любом случае, насколько мне известно, когда компилятор выполняет проверку типов, он основывает эту проверку на "дереве разбора", которое генерирует таблицу вида для всех возможных структур типов данных и проверяет, указывают ли два определения на одну и ту же строку.в таблице.Так что он работает, выбирая символы и определения типов из этой таблицы и сравнивая их.Теперь "struct objc_object" является одной из этих структур данных.Затем, когда идентификатор определен, он генерирует еще одну запись: "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», но дажеесли логически они одинаковы, они не приводят к одной и той же ссылке в таблице.Причина в том, что тип «O» еще не определен, поэтому po_two просто сохраняется в таблице символов как указатель на «O» и «O -> struct objc_object».И вот причина предупреждения: po_two - это указатель на что-то отличное от @ "two".

У меня есть любопытство: вы пытались построить таблицу символов, используя "nm"?

...