Является ли struct { ... }; типом или неназванной переменной?

является ли следующее в области файла объявлением типа или неназванной переменной?

struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

Если это определение типа, то в чем разница с:

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

?

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

Примечание: вопрос был помечен как возможный дубликат в какую область помещается идентификатор члена структуры? но я считаю, что я задаю вопрос не о сфере охвата членов, а о том, что на самом деле создают декларации. Однако. ответы разница между "struct" и "typedef struct" в C++? объясните мой вопрос.

6 ответов


на C standard, объявление структуры в виде

struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

- это объявления тип. Цитата C11 глава §6.7.2.1

наличие struct-declaration-list в описателе структуры или объединения объявляет новый тип в единице перевода. Struct-declaration-list-это последовательность объявлений для членов структуры или объединения. [...]

C стандарт не не мандат создания переменная (С именем или без имени) для этого типа.

во втором фрагменте вы на самом деле (попытаться) typedef to ничего. Однако, если вы измените свой фрагмент в виде

typedef struct {
         //.....members
} student_s ;

вы будете создавать тип student_s (typedef к неназванному типу структуры), который вы можете использовать позже.

FWIW, мы никогда поговорили о переменная создается здесь, в любом случае. Это все о типы.


первое объявление объявляет тип. После этого объявления введите struct student_s известно, и вы можете объявить переменные этого типа или указатель на него:

struct student_s student1;
struct student_s *pStudent;

второе объявление странно, даже если оно компилируется. Общее использование было бы:

typedef struct {
    char* name;
    int age;
    double height;
    struct student_s* next;   
} studend_t;

который объявляет псевдоним student_t на анонимной структуры. Затем его можно использовать напрямую:

student_t student1;
student_t *pStudent;

но второй пример компилируется (даже с предупреждением) и совпадает с ПЕРВЫЙ !

на самом деле он объявляет псевдоним void struct student_s. Typedef игнорируется и выдает предупреждение:typedef требует имя, но в качестве побочного эффекта структура объявляется точно так же, как и в первом примере.

таким образом, истинный ответ на фактический вопрос НЕТ НИКАКИХ РАЗЛИЧИЙ за исключением предупреждение.


оба определения типа. Второй-неполный. Он не предоставляет имя в качестве аргумента typedef. Гораздо лучше использовать

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
} student;


относительно законности

typedef struct student_s {
    char* name;
    int age;
    double height;
    struct student_s* next;   
};

Я задал это как отдельный вопрос,законность ' typedef struct foo {int bar};'


это тип, и вы не можете иметь анонимный экземпляр структуры. Для сравнения, это объявляет оба типа struct_type и экземпляр struct_instance такого типа:

struct struct_type {
    /* blah */
} struct_instance;

если вы хотите объявить другой экземпляр изолированно (от типа decl), вы бы использовали

struct struct_type another_instance;

использование typedef-если сделано правильно, в отличие от вашего примера - просто позволяет дать типу другое имя, которое не требует struct ключевое слово для объявления пример:

typedef struct_type MyStruct;
MyStruct yet_another_instance;

или

typedef struct struct_type {
    /* blah */
} MyStruct;

опуская имя (struct_type) дает вам анонимный тип структуры, который может ссылаться только на его имя typedef'D.


Примечание 1

так как ваша оригинальная структура содержит next указатель на свой собственный тип, Этот тип должно быть имя в точке объявляется член. Итак, ты!--13-->не может объявить анонимный struct с собой типизированный указатель. Если вы даете своему анонимному типу структуры имя с typedef, это имя не существует до объявления члена, поэтому его нельзя использовать там.

typedef struct /*S*/ {
    struct S *next; /* T doesn't exist yet, so without S, you can't declare this */
} T;

примечание 2.

вы можете объявить анонимный экземпляр анонимного Союза в качестве члена:

struct S {
    union {
        int i;
        unsigned u;
    };
};

struct S s;
s.i = -1;
printf("%x\n", s.u);

но это особый случай. Я взял замечание об этом из основного аргумента, на случай, если оно вводит в заблуждение.


разница в том, что и в первом примере, вы должны объявить новую переменную так: struct student_s variable;, однако со вторым примером вы можете просто сделать student_s variable;.


struct A { ... }

создает struct' A ' виден в struct пространство имен (которое не имеет ничего общего с пространствами имен C++). Итак, для доступа struct вы должны использовать struct ключевое слово;

struct A a;

при определении с помощью typedef struct

typedef struct A { ... } B;

становится видимым и привязанным к B, и вы можете легко создать struct как общая переменная типа B

B a;

пожалуйста, поправьте меня кто, если я ошибаюсь.