Декларация ничего не объявляет: предупреждение?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

int main()
{
    struct emp
    {
        struct address
        {
              int a;
        };
        struct address a1;
    };
}

Этот код показывает предупреждение: -

warning: объявление не объявляет ничего (включено по умолчанию)

Если в следующем коде не отображается предупреждение

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

int main()
{
    struct emp
    {
        struct address
        {
             int a;
        }a1;
    };
}   

Почему "предупреждение" отображается только в первом коде?

Ответ 1

Причина, по которой компилятор показывает предупреждение, состоит в том, что он не видит имя переменной типа address, которую вы определили для структуры emp, даже если вы do объявите что-то использует address на следующей строке, но я думаю, что компилятор недостаточно умен, чтобы понять это.

Как вы показали, это вызывает предупреждение:

struct emp {
  struct address {}; // This statement doesn't declare any variable for the emp struct.
  struct address a1;
};

Но не это:

struct emp {
  struct address {} a1; // This statement defines the address struct and the a1 variable.
};

Или это:

struct address {};

struct emp {
  struct address a1; //the only statement declare a variable of type struct address
};

struct emp {} не отображает никаких предупреждений, так как этот оператор не находится внутри блока детекции структуры. Если вы положили его внутри одного из них, тогда компилятор также покажет предупреждение. Ниже приводятся два предупреждения:

struct emp {
  struct phone {};
  struct name {};
};

Ответ 2

Синтаксис определения структуры:

struct identifier {
    type member_name;

    // ...

};

Если вы добавите идентификатор сразу после закрытия фигурной скобки, вы объявляете переменную с указанной структурой.

В вашем первом примере компилятор рассматривает структуру address как тип члена. это нравится, если вы пишете:

struct identifier {

    type ; // No member name is specified
    type a1;

    // ...

}

Но во втором примере вы указали имя члена:

struct identifier {

    type a1; // Member name specified

    // ...

}

И вот пример предупреждения: http://ideone.com/KrnYiE.

Ответ 3

Причина, по которой отображается предупреждение, заключается в том, что первый отрывок не является правильным. C - он имеет ограничение ограничения, которое компилятор C, соответствующий стандартам, должен выдать диагностическое сообщение. Он нарушает C11 6.7.2.1p2:

Ограничения

  1. Объявление структуры, которое не объявляет анонимную структуру или анонимный союз, должно содержать список struct-declarator.

Это означает, что это нормально писать

struct foo {
    struct {
          int a;
    };
};

так как внутренняя struct объявляет анонимную структуру, то есть она не называется.

Но в вашем примере struct address имеет имя- address - и, следовательно, он должен иметь список деклараторов после того, как список закрывающих списков фигур, например, a1 как в вашем примере, или более сложный foo, *bar, **baz[23][45].