Определения типов, теговые и непомеченные структуры и несовместимые типы указателей
Рассмотрим следующий фрагмент кода C:
typedef struct node{
int val;
struct node* left;
struct node* right;
}node;
void inorderTraversal(node *p){
inorderTraversal(p->left);
printf("%d",p->val);
inorderTraversal(p->right);
}
Если я пишу только typedef struct
вместо typedef struct node
Я получаю предупреждение о том, что "передавая аргумент несовместимого типа указателя" при вызове inorderTraversal(root)
в main()
, Почему я получаю это предупреждение, даже если в программе нет ошибок?
3 ответа
Если вы не дадите имя тега для структуры,
struct node* left;
в определении структуры объявляется новый (неполный) тип struct node
, Поэтому, когда вы передаете указатель на этот (неполный) тип, где node*
ожидается, вы передаете указатель несовместимого типа.
Когда определяемая вами структура имеет члены, которые являются указателями на один и тот же тип, вы должны иметь возможность назвать этот тип в определении, поэтому тип должен находиться в области видимости.
Если вы даете struct
имя, тип - с этого момента - в области видимости и может упоминаться, хотя еще не завершено, как struct node
(если тег node
). После того, как typedef завершен, тип может называться либо struct node
или же node
какой вы предпочитаете.
Но если вы не дадите struct
тэг, тип является анонимным, пока typedef не завершен, и на него нельзя ссылаться до этого. И с тех пор, когда линия
struct node *left;
встречается, типа нет struct node
ссылается, как известно, эта строка объявляет новый тип, struct node
о которых ничего не известно. У компилятора нет причин связывать этот тип с тем, который определен в данный момент. Итак, на данный момент, struct
содержит член, который является указателем на неизвестный неполный тип. Сейчас в inorderTraversal
когда вы звоните
inorderTraversal(p->left);
с node *p
по определению node
, p->left
указатель на неизвестный неполный тип struct node
, Если p
был создан так, чтобы p->left
на самом деле указатель на node
Тем не менее, все будет работать (за исключением, возможно, на платформах, где указатели на разные типы имеют разные представления), но вы передаете указатель на один тип, где ожидается указатель на другой тип. Поскольку один тип является неполным, он несовместим с ожидаемым типом.
"passing argument of incompatible pointer type"
Потому что узел неизвестен в то время. Так что это рассматривается как новый тип.
struct node{
int val;
struct node* left;
struct node* right;
};
void inorderTraversal(struct node *p){
inorderTraversal(p->left);
printf("%d",p->val);
inorderTraversal(p->right);
}
Теперь узел объявляется как структура перед его использованием. т.е. struct node* left;
так что ошибки нет.
Пожалуйста, обратитесь к этому также: самоопределение определения структуры?
C структура с указателем на себя
Вы не можете создать аноним typedef
У него должно быть имя. C не поддерживает анонимный struct
типы.
Расширение GCC включит эту функцию, хотя: -fms-extensions