typedef struct против struct определений [дубликат]

Вы довольно быстро сломаете любой тип данных, поскольку числа монтируются вверх.

Использование LOG / EXP сложно из-за чисел & lt; = 0, которые будут сбой при использовании LOG. Я написал решение в этого вопроса , касающееся этого

736
задан Francesco Boi 4 December 2018 в 16:22
поделиться

8 ответов

Общая идиома использует оба:

typedef struct X { 
    int x; 
} X;

Это разные определения. Чтобы сделать обсуждение более ясным, я разделю предложение:

struct S { 
    int x; 
};

typedef struct S S;

В первой строке вы определяете идентификатор S в пространстве имен структур (не в смысле C ++). Вы можете использовать его и определять переменные или аргументы функций нового определенного типа, определяя тип аргумента как struct S :

void f( struct S argument ); // struct is required here

Вторая строка добавляет псевдоним типа S в глобальное пространство имен и, таким образом, позволяет вам просто написать:

void f( S argument ); // struct keyword no longer needed

Обратите внимание, что, поскольку оба пространства имен идентификаторов различны, определение S как в структурах, так и в глобальных пространствах не является ошибкой, поскольку не переопределяет тот же идентификатор, но вместо этого создается другой идентификатор в другом месте.

Для большей ясности:

typedef struct S { 
    int x; 
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

Вы можете определить функцию с тем же именем структуры, что и идентификаторы, хранящиеся в разных пространствах, но вы не можете определить функцию с тем же именем, что и typedef , поскольку эти идентификаторы сталкиваются.

В C ++ он немного отличается, поскольку правила поиска символа слегка изменились. C ++ по-прежнему сохраняет два разных пространства идентификаторов, но в отличие от C, когда вы определяете символ только в пространстве идентификаторов класса, вам не требуется указывать ключевое слово struct / class:

 // C++
struct S { 
    int x; 
}; // S defined as a class

void f( S a ); // correct: struct is optional

Какие изменения относятся к правилам поиска, а не где идентификаторы определены. Компилятор будет искать в таблице глобальных идентификаторов и после того, как S не будет найден, он будет искать S в идентификаторах классов.

Код, представленный ранее, ведет себя таким же образом:

typedef struct S { 
    int x; 
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

После определения функции S во второй строке, структура S не может быть автоматически разрешена компилятором, и для создания объекта или определения аргумента этого типа вы должны вернуться к включению ключевое слово struct :

// previous code here...
int main() {
    S(); 
    struct S s;
}
954
ответ дан 22 November 2019 в 21:24
поделиться

Другое незаметное отличие заключается в том, что присвоение структуре имени (например, struct myStruct) также позволяет вам предоставлять предварительные объявления структуры. Итак, в каком-нибудь другом файле вы можете написать:

struct myStruct;
void doit(struct myStruct *ptr);

, не имея доступа к определению. Я рекомендую вам объединить ваши два примера:

typedef struct myStruct{
    int one;
    int two;
} myStruct;

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

89
ответ дан 22 November 2019 в 21:24
поделиться

Я бы порекомендовал что-то вроде этого:

def combine_lists(list1, list2):
    s = set(list1)
    s.update(list2)
    return list(s)

Это устраняет проблему создания чудовищный список конкатенации первых двух

В зависимости от того, что вы делаете с выводом, не беспокойтесь о преобразовании обратно в список. Если порядок важен, вам могут понадобиться какие-то махинации по украшению / сортировке / недекорированию.

Префикс struct больше не нужен.

31
ответ дан 22 November 2019 в 21:24
поделиться

В C ключевые слова спецификатора типа структур, объединений и перечислений являются обязательными, т. Е. Вы всегда должны добавлять префикс имени типа (его тег ) с помощью struct , union или enum при ссылке на тип.

Вы можете избавиться от ключевых слов, используя typedef , который является формой скрытия информации, поскольку фактический тип объекта больше не будет виден при его объявлении.

Поэтому рекомендуется (см., например, Руководство по стилю кодирования ядра Linux , Глава 5), только когда на самом деле вы хотите, чтобы скрыл эту информацию, а не только для сохранения нескольких нажатий клавиш.

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

23
ответ дан 22 November 2019 в 21:24
поделиться

typedef , как и другие конструкции, используется для присвоения типу данных нового имени. В данном случае это в основном делается для того, чтобы код был чище:

struct myStruct blah;

vs.

myStruct blah;
4
ответ дан 22 November 2019 в 21:24
поделиться

В последнем примере вы опускаете ключевое слово struct при использовании структуры. Таким образом, везде в вашем коде вы можете написать:

myStruct a;

вместо

struct myStruct a;

Это сэкономит время на вводе текста и может быть более читаемым, но это дело вкуса

2
ответ дан 22 November 2019 в 21:24
поделиться

В C (не C ++) вы должны объявить структурные переменные, например:

struct myStruct myVariable;

Чтобы иметь возможность использовать myStruct myVariable; вместо этого, вы можете ] typedef структура:

typedef struct myStruct someStruct;
someStruct myVariable;

Вы можете объединить определение struct и typedef в одном операторе, который объявляет анонимную структуру и ] typedef и все.

typedef struct { ... } myStruct;
55
ответ дан 22 November 2019 в 21:24
поделиться

Разница возникает, когда вы используете структуру struct .

Первый способ, который вам нужно сделать:

struct myStruct aName;

Второй способ позволяет удалить ключевое слово struct .

myStruct aName;
5
ответ дан 22 November 2019 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: