Пожалуйста, объясните правила синтаксиса и область действия для "typedef" - PullRequest
30 голосов
/ 11 марта 2010

Каковы правила?OTOH простой случай, кажется, подразумевает, что новый тип - последняя вещь в строке.Как здесь Uchar - это новый тип:

typedef unsigned char Uchar;

Но указатель на функцию совершенно другой.Здесь новый тип pFunc:

typedef int (*pFunc)(int);

Я не могу придумать другие примеры, но я столкнулся с некоторыми очень запутанными употреблениями.

Так есть правила илилюди просто должны были знать из опыта, что именно так это и делается, потому что они видели, как это делалось раньше?

ТАКЖЕ: Какова сфера действия typedef?

Ответы [ 2 ]

59 голосов
/ 11 марта 2010

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

A typedef определяется в точности так, как это было бы с объявлением объекта, поэтому он может быть областью видимости файла или локальным для блока или (в C ++) для пространства имен или класса.

, например

Объявляет int:

int a;

Объявляет тип, который является псевдонимом для int:

typedef int a_type;

Объявляет указатель на char:

char *p;

Объявляет псевдоним для char *:

typedef char *pChar;

Объявляет указатель на функцию:

int (*pFn)(int);

Объявляет псевдоним для типа 'указатель на функцию, принимающую int и возвращающую int':

typedef int (*pFunc)(int);
4 голосов
/ 22 января 2015

Для удобства синтаксиса typedef обрабатывается как спецификатор класса хранения , например extern, static или register. Семантически, конечно, все по-другому, но когда к языку добавили typedef, было проще использовать существующий фрагмент грамматики для определения его синтаксиса.

Добавление static к объявлению объекта не меняет смысла объявления за исключением того, что меняет класс хранения объекта на «статический» (если он еще не был):

{
    int foo; /* automatic storage duration */
    static int bar; /* static storage duration */
}

Замена static на typedef изменяет смысл объявления, так что определяемое имя - это не имя объекта, а имя типа (фактически просто псевдоним для существующего типа):

    typedef int baz; /* "baz" is an alias for "int" */

Тот же синтаксис применяется к более сложным объявлениям:

int (*a)[42];         /* a is a pointer to an array of 42 ints */
static int (*b)[42];  /* Same as a, but with static storage duration */
typedef int (*c)[42]  /* c is an alias for the type int(*)[42], or 
                         "pointer to array of 42 ints" */

Как только вы поймете, что typedef было произвольно вставлено в тот же слот в грамматике, занимаемой extern, static и register, понимание объявлений typedef не сложнее (и не проще!), Чем понимание объявлений объекта. (Программа cdecl и веб-сайт полезны для распаковки сложных объявлений.)

Вы также можете иметь typedef для типа функции:

void func(void);              /* declare func as a function */
typedef void func_type(void); /* declare func_type as a name
                                 for a function type */

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

func_type *ptr = func;

Что касается scope (имеется в виду область программного текста, в которой виден объявленный идентификатор), идентификатор, определенный объявлением typedef, имеет ту же область, что и любой другой объявленный идентификатор. Если он объявлен в области видимости файла, вне какой-либо функции, он виден от точки объявления до конца файла. Если он объявлен внутри функции, он виден с точки, в которой он объявлен, до конца ближайшего окружающего блока. Как и любое объявление, оно может быть скрыто другим объявлением с таким же именем во внутренней области видимости.

...