Использование ключевого слова struct в объявлении переменной в С++

У меня такое чувство, что это может быть связано с синтаксисом Си, но я начал свою жизнь программирования с С++, поэтому не уверен.

В основном я видел это:

struct tm t;
memset( &t, 0, sizeof(struct tm) );

Я немного смущен этим синтаксисом, так как обычно я ожидал бы, что выше это будет выглядеть следующим образом:

tm t;
memset( &t, 0, sizeof(tm) );

В чем разница между двумя, и почему вместо этого используется первая?

Update

Структура tm, о которой я говорю, находится в wchar.h, и определение выглядит следующим образом:

struct tm {
        int tm_sec;     /* seconds after the minute - [0,59] */
        int tm_min;     /* minutes after the hour - [0,59] */
        int tm_hour;    /* hours since midnight - [0,23] */
        int tm_mday;    /* day of the month - [1,31] */
        int tm_mon;     /* months since January - [0,11] */
        int tm_year;    /* years since 1900 */
        int tm_wday;    /* days since Sunday - [0,6] */
        int tm_yday;    /* days since January 1 - [0,365] */
        int tm_isdst;   /* daylight savings time flag */
        };

Ответы

Ответ 1

Простой ответ заключается в том, что ключевое слово struct присутствует, чтобы ограничить поиск идентификатора tm только определяемыми пользователем типами классов. Вероятно, он оставлен для совместимости с C, где это необходимо.

Вопреки тому, что говорят другие, нет такой вещи, как auto-typedef, и не различаются C и С++ в отношении того, как управляются идентификаторы для пользовательских типов. Единственное различие заключается в поиске.

Здесь вы можете прочитать

Ответ 2

В C имена тегов структуры не формируют идентификаторы в глобальном пространстве имен

struct not_a_global_identifier { /* ... */ };

Чтобы ссылаться на эту структуру, вы должны использовать ключевое слово struct (чтобы указать пространство имен)

struct not_a_global_identifer object;

или создайте новый идентификатор в глобальном пространстве имен с помощью typedef

typedef struct not_a_global_identifer { /* ... */ } global_name_space_identifier;

В C существует 4 пространства имен, см. 6.2.3 в C99 Standard:

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

Это законная программа C: -)

int main(void) {
  typedef struct foobar { int foobar; } foobar;
  foobar boo;
  boo.foobar = 42;
  if (boo.foobar) goto foobar;
foobar:
  return 0;
}

Ответ 3

Пользовательские типы имеют собственное пространство идентификаторов, то есть когда компилятор анализирует файл, он сохраняет каждый идентификатор в соответствующем пространстве.

Когда вы ссылаетесь на tm, компилятор C (как на С++) будет искать этот идентификатор в пространстве глобального идентификатора. Затем компилятор С++ будет искать в пользовательском пространстве идентификаторов типов, если ранее не нашел символ.

В принципе, если вы хотите иметь такое же поведение, как на С++, добавьте эту строку:

typedef struct tm tm;

Вы можете объединить объявление структуры и typedef следующим образом:

typedef struct tm { int field } tm;

Или используя анонимную структуру:

typedef struct { int field } tm;

То же самое относится к enum и union:

typedef enum { VALUE } myEnum;
typedef union { int integer; char charArray[4]; } myUnion;

Ответ 4

Использование struct tm t; для совместимости с C, в котором объявление структуры с именем "tm" определяет тип с именем "struct tm", но не один с именем "tm" (в отличие от С++, в котором оба имени для типа объявлены).

Ответ 5

В вашем примере tm может быть типизированной структурой.

например.

typedef struct tm_t
{
  int x; 
}tm;

а затем вы можете сделать

tm t; 

Ответ 6

Вы можете увидеть ссылку, приведенную ниже, и цитату оттуда "В C, вы должны явно использовать ключевое слово struct для объявления структуры. В С++ это необязательно после определения типа". См. Ссылку для получения дополнительной информации и примеров.

http://msdn.microsoft.com/en-us/library/64973255%28v=vs.80%29.aspx