Использование ключевого слова 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