недавно я нашел typedef
в моем коде работает действительно отличается от того, что я предложил. Пример как это:
typedef int *ptype;
ptype v1 = 0, v2 = 0;
Результат: оба v1 и v2 были определены как указатель на int
тип. Но если вы просто замените ptype
от int *
во втором предложении как int *v1 = 0, v2 = 0;
или же int* v1 = 0, v2 =0;
, только v1 будет указателем, а v2 нормальным int
, Похоже на то typedef
не делает простую замену. Более того, когда дело доходит до усложнения модификатора, такого как:
typedef int *ptype;
const ptype v3 = 0;
Результат будет: v3 является const
указатель, а не указатель на const
Int, если мы напишем const int *v3 = 0;
, В приведенном выше коде const
выступает в качестве модификатора для всего ptype
, не int
внутри ptype
, Таким образом, это действительно выглядит typedef
объединяет составной тип int*
и создает новый тип.
Тем не менее, авторитетный C / C ++ справочный сайт cplusplus говорит «typedef не создает разные типы. Он только создает синонимы существующих типов». так что я был действительно смущен и надеюсь, что кто-то может помочь объяснить поведение typedef
, Спасибо!
«Синоним» не означает «замена текста». ptype
буквально не расширяется до int *
препроцессором или чем-то еще.
Это означает, что вы можете делать такие вещи, как:
typedef int *ptype;
ptype a;
int *b;
a = b; // OK
Назначение действительно, потому что ptype
а также int *
одинакового типа; здесь не требуется преобразование типов или приведение типов.
typedef
просто позволяет дать новое имя существующему типу. Но это имя объединяет каждый аспект существующего типа в неделимую сущность, например, такую как ptype a, b;
эквивалентно ptype a; ptype b;
(а также const ptype
означает «const указатель на int», потому что ptype
означает «указатель на int»).
Другими словами, новый имена создано typedef
вести себя как встроенные ключевые слова в том, что касается объявления, но фактическое типы представленные этими именами одинаковы.
Когда cplusplus.com говорит, что typedef
не создает новый тип, они имеют в виду, что где угодно вы можете использовать значение ptype
Вы также можете использовать значение типа int*
и наоборот. Так что, если вы определите функцию, которая принимает ptype
параметр, вы можете передать его int*
без каких-либо преобразований, необходимых.
Это не значит, что typedef
реализован в виде чисто текстовой замены, как #define
было бы.
Ссылаясь на C89, раздел 3.5, вот причина того, что ptype v1 = 0, v2 = 0;
не эквивалентно int *v1 = 0, v2 = 0;
, Более поздние версии C и C ++ были проинформированы C89 и по сути одинаковы в этом отношении.
В ptype v1 = 0, v2 = 0;
, ptype
является «спецификатором объявления», и v1 = 0, v2 = 0
это «список инициаторов объявления». В частности, ptype
является «спецификатором типа» и, более конкретно, это «имя-определения типа». Итак, мы объявляем две переменные (v1
а также v2
) оба из которых имеют тип ptype
, что является еще одним именем для int*
,
В int* v1 = 0, v2 = 0
, int*
является не «спецификаторы объявления», потому что они состоят из серии «спецификатор типа», «спецификатор класса хранения» и «спецификатор типа». Вы можете посмотреть каждый из них по очереди, но все вместе они составляют целый список ключевых слов, таких как static
или же const
встроенные имена типов, а также имена типов и перечислений и спецификаторы struct / union. Oни не включить *
, который является частью синтаксиса для составного типа. Так что в этом случае int
это «спецификатор объявления и *v1 = 0, v2 = 0
это «список инициатора объявления». Как только мы разобьем грамматику «списка инициаторов объявления», *
относится только к v1
не v2
, Вот почему он определяет один int*
и один int
,
Точно так же вы могли бы написать ptype *v1 = 0, v2 = 0;
, который определил бы один pytpe*
и один ptype
, То есть один int**
и один int*
,
Грамматика для const int *
против const ptype
получается аналогичный результат — в первом случае const
«квалификатор типа» относится к int
но в последнем это относится к ptype
,