Следующее определяет A
для замены на B
:
#define A B
Принимая во внимание, что это определяет A
как псевдоним для типа B
:
typedef B A;
Почему ? Разве это не бессвязно?
Следующее определяет A
для замены на B
:
#define A B
Принимая во внимание, что это определяет A
как псевдоним для типа B
:
typedef B A;
Почему ? Разве это не бессвязно?
Проще говоря: рассмотрите следующие объявления переменных:
// declare a variable called "myInt" with type int
int myInt;
// declare a variable called "myDouble" with type double
double myDouble;
// declare a variable called "myLong" with type long
long myLong;
// declare a variable called "myFunc" with type pointer to function
void (*myFunc)(char*);
Тогда typedef
имеют смысл:
// declare a type alias called "myInt" with type int
typedef int myInt;
// declare a type alias called "myDouble" with type double
typedef double myDouble;
// declare a type alias called "myLong" with type long
typedef long myLong;
// declare a type alias called "myFunc" with type pointer to function
typedef void (*myFunc)(char*);
Макросы, с другой стороны, могут иметь синтаксис функционального стиля:
#define A(B, C) B, C
A(1, 2) // expands out to 1, 2
Таким образом, для макросов «определение», следующее за «именем», имеет больше смысла.
(Кстати, это относится и к C++.)
Да, с макросами вообще беда.
typedef
был добавлен в язык довольно давно после того, как большая часть остального языка была завершена. Он использует тот же синтаксис, что и класс хранилища:
static int x;
extern int y;
typedef int z;
Они определяют x
, y
и z
как int
-- разница в том, что x
и y
являются объектами типа int
, а z
в основном является псевдонимом самого int
.
Таким образом, typedef
достаточно хорошо вписывается в язык, и это (как обычно) препроцессор, который действительно является «лишним». В то же время вы можете утверждать, что остальная часть языка также должна измениться. Просто для наглядного примера Паскаль грубо изменил порядок вещей:
type
z = integer;
var
x : integer;
Хотя это не имеет большого значения для тривиальных примеров, я думаю, что это гораздо проще читать, особенно когда вы имеете дело с более сложными объявлениями. Однако, к лучшему или к худшему, Паскаль (в основном) потерял популярность, а более новые языки, такие как Java, сохранили эту конкретную часть синтаксиса C (т. Е. Та часть C, которую они сохранили, больше всего нуждалась в изменении) .
Поскольку A
в typedef
может быть несколькими символами, например. typedef int Integer, *PInteger;
. Это согласуется с тем, как определяются переменные (int var, *pvar;
).
Typedef с точки зрения синтаксиса языка находится в группе storage class specifier
вместе с extern
и static
(*), и, таким образом, typedef занимает то же место, что и они. Он явно не принадлежит к этой группе, но я предполагаю, что он, вероятно, был там, где он был наименее неуместным.
(*) Класс хранения также включает auto
и register
, но их больше никто не использует.
Я не знаю, почему, что касается языковых решений, но то, как typedef имеет смысл для меня.
Спецификатор typedef
является частью языка. Он служит способом псевдонима типа для некоторого имени. Вы всегда можете указать тип в объявлении переменной.
struct arr { int len; char *chars; } name;
struct arr another_name;
Использование typedef
отражает это использование, за исключением того, что вместо объявления переменной для типа вы объявляете имя для типа.
typedef struct { int len; char *chars; } arr;
arr name;
arr another_name;
Директива #define
является частью препроцессора, а не языка, поэтому она не привязана к тому, как язык представляет определенные конструкции, и может использовать более естественный способ ее объявления.
Потому что препроцессор и компилятор — это фактически две разные программы, каждая со своим синтаксисом. Можно было совместить препроцессор с другими языками без особого труда (в прежние времена я делал это, используя cpp
в программах dBase III и AutoLISP, потому что в этих языках не было хорошего механизма включения констант). Как уже указывали другие, typedef
следует синтаксису системы объявлений C, а #define
представляет собой простое прямое объявление подстановки.
Да, синтаксис typedef меня тоже немного сбивает с толку. Я предполагаю, что ваш вопрос больше похож на жалобу - C почти 40 лет, вы не ожидаете, что синтаксис typedef изменится, не так ли?
typedef
, который создает просто псевдоним типа, способ создания нового типа из старого —type NewType OldType
. Интересно, будут ли он и Деннис Ритчи спорить лицом к лицу о синтаксических решениях, которые Go явно делает похожими на C, но отличающимися от C. Порядок объявления в Go в основном противоположный :-) - person Steve Jessop   schedule 28.02.2011