Подтвердить что ты не робот

Пожалуйста, объясните правила синтаксиса и область действия для "typedef"

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

typedef unsigned char Uchar;

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

typedef int (*pFunc)(int);

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

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

ТАКЖЕ: Какова область действия typedef?

4b9b3361

Ответ 1

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

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

например.

Объявляет int:

int a;

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

typedef int a_type;

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

char *p;

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

typedef char *pChar;

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

int (*pFn)(int);

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

typedef int (*pFunc)(int);

Ответ 2

Для удобства синтаксиса 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;

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