Определения типов, теговые и непомеченные структуры и несовместимые типы указателей

Рассмотрим следующий фрагмент кода 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

Другие вопросы по тегам