Фундаментальный синтаксис операнда typedef

Дано:

typedef type-declaration synonym;

Я вижу, как:

typedef long unsigned int size_t;

объявляет size_t синонимом long unsigned int, однако я (знаю, что это так, но) не вижу, точно как:

typedef int (*F)(size_t, size_t);

объявляет F синонимом pointer to function (size_t, size_t) returning int

Два операнда typedef (type-declaration, synonym) в первом примере — это long unsigned int и size_t.

Каковы два аргумента typedef в объявлении F или, возможно, существуют перегруженные версии typedef?

Если есть соответствующее различие между C и C++, пожалуйста, уточните, иначе меня в первую очередь интересует C++, если это поможет.


person Peter McG    schedule 23.09.2010    source источник
comment
Просто для уточнения исходного исходного синтаксиса отсюда: msdn.microsoft.com/en-us/library/05w82thz%28v=VS.100%29.aspx   -  person Peter McG    schedule 24.09.2010
comment
не верьте всему, что вам говорит Microsoft ;-)   -  person Steve Jessop    schedule 24.09.2010
comment
Объявления указателя на функцию — один из самых странных синтаксисов в C. Единственное, что я видел, было более странным, — это синтаксис указателя на член в C++... И это потому, что он напоминает синтаксис указателя на функцию в C.   -  person Mike DeSimone    schedule 24.09.2010
comment
@Steve: Спасибо :) Я бы об этом не мечтал: по моему опыту подозрения обычно здоровы, что на самом деле привело к этому вопросу в этом случае.   -  person Peter McG    schedule 24.09.2010


Ответы (5)


Объявления типов с использованием typedef аналогичны соответствующим объявлениям переменных, только с добавлением typedef. Так,

        int x; // declares a variable named 'x' of type 'int'
typedef int x; // declares a type named 'x' that is 'int'

То же самое и с типами указателей на функции:

        int(*F)(size_t); // declares a variable named F of type 'int(*)(size_t)'
typedef int(*F)(size_t); // declares a type named 'F' that is 'int(*)(size_t)'

Это не «особый случай»; именно так выглядит тип указателя на функцию.

person James McNellis    schedule 23.09.2010
comment
Это очень полезно, спасибо, теперь я сразу вижу разницу, что все еще немного сбивает с толку, так это «два аргумента», я прав, поясняя, что для typedef int(*F)(size_t); есть только один аргумент для typedef? - person Peter McG; 24.09.2010
comment
@Peter: Это вообще не аргумент; это просто синтаксис объявления. int(*)(size_t) — это тип указателя на функцию, которая возвращает int и имеет единственный параметр типа size_t. Функция, на которую указывает такой указатель, должна принимать один аргумент (типа size_t), но здесь это единственный аргумент. - person James McNellis; 24.09.2010
comment
@Peter: typedef это не функция, она не принимает аргументов. Он превращает объявление переменной в объявление типа. - person GManNickG; 24.09.2010
comment
Теперь я вижу, как правильно читать объявление типа с помощью typedef, это не было очевидно из нескольких разных источников документации, которые я читал до сих пор - спасибо! - person Peter McG; 24.09.2010

Это не формальный синтаксис typedef, это всего лишь один из шаблонов, которые он может использовать. В стандарте C 6.7.1 typedef синтаксически определяется как спецификатор класса хранения (например, extern или static). Он изменяет объявление, так что объявление объявляет псевдоним типа вместо объекта.

typedef не является ни функцией, ни оператором, поэтому понятия "аргумент", "операнд" или "перегрузка" к нему неприменимы. Он просто сообщает компилятору, какое объявление вы делаете.

В C++ typedef синтаксически определяется как спецификатор decl, а не спецификатор класса хранения. storage-class-specifiers также являются decl-specifiers, как и friend. Я не думаю, что это имеет какое-то практическое значение, это еще один способ сказать то же самое, что говорит C, но это 7.1 стандарта C++, если вы хотите посмотреть сами. Признаюсь, пока это меня сбивает с толку.

person Steve Jessop    schedule 23.09.2010
comment
Это также очень полезно, хотя я все еще мог бы уточнить количество аргументов для typedef, стоит ли включать здесь правильный синтаксис typedef или, возможно, ссылку для уточнения вашего первого предложения? - person Peter McG; 24.09.2010
comment
@Peter: typedef не имеет аргументов, точно так же, как static не имеет аргументов или const не имеет аргументов. У него также нет собственного синтаксиса. Это модификатор, застрявший в начале объявления, поэтому он является частью синтаксиса объявления. Синтаксис объявления и семантика в основном занимают все главы 7 и 8 стандарта C++. - person Steve Jessop; 24.09.2010
comment
Я думаю, что C++ имеет это различие, потому что вы можете поместить спецификаторы класса хранения внутри спецификаторов decl, но не наоборот. Например. 'typedef const static int foo;' нормально, но 'static typedef const foo int;' не является. - person Mike DeSimone; 24.09.2010

Ваше первоначальное предположение о синтаксисе typedef, имеющем

typedef type-declaration synonym;

структура абсолютно неверная. Синтаксис Typedef не имеет такой структуры и никогда не имел.

Синтаксис Typedef аналогичен обычному объявлению, подобно любому другому объявлению в языке C. Ключевое слово typedef — это просто спецификатор объявления, указывающий, что объявленное имя является именем typedef, а не переменной, указателем функции или чем-то еще.

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

typedef int TInt, *TIntPtr, (*TIntFuncPtr)(void), TIntArr10[10];
person AnT    schedule 23.09.2010

Вместо того, чтобы думать о typedef как об операции, которая принимает два параметра (тип и синоним), подумайте об этом как о квалификаторе типа. Чтобы объявить переменную с именем F, которая была указателем на функцию, принимающим два параметра size_t и возвращающим int, вам нужно было бы просто:

int (*F)(size_t, size_t);

Добавьте квалификатор типа typedef, и вместо объявления переменной вы объявите псевдоним типа.

person llasram    schedule 23.09.2010

typedef использует синтаксис объявления.

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

person linuxuser27    schedule 23.09.2010