Почему операнды #define и typedef инвертированы? - PullRequest
5 голосов
/ 27 февраля 2011

Следующее определяет A как замененный на B:

#define A B

В то время как A определяет псевдоним для типа B:

typedef B A;

Почему?Разве это не бессвязно?

Ответы [ 7 ]

7 голосов
/ 27 февраля 2011

Проще говоря: рассмотрим следующие объявления переменных:

// 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 ++.)

4 голосов
/ 27 февраля 2011

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

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;

Хотя это не имеет большого значения для тривиальных примеров, я думаю, что это довольно просто читать, особенно когда вы имеете делос более сложными декларациями.Однако, к лучшему или худшему, Pascal (в основном) потерял популярность, и более новые языки, такие как Java, сохранили эту конкретную часть синтаксиса C (т. Е. Та часть C, которую они сохранили, была единственной вещью, которая нуждалась в изменении).

2 голосов
/ 27 февраля 2011

Typedef с точки зрения синтаксиса языка в группе storage class specifier вместе с extern и static (*), и, следовательно, typedef имеет такое же расположение, как и те.Он явно не относится к этой группе, но я думаю, что, вероятно, он был там, где он был наименее ошибочно размещен.

(*) Класс хранения также включает в себя auto и register, но никто их больше не использует.

2 голосов
/ 27 февраля 2011

Поскольку A в typedef может быть несколькими символами, например, typedef int Integer, *PInteger;. Это согласуется с тем, как определяются переменные (int var, *pvar;).

1 голос
/ 28 февраля 2011

Поскольку препроцессор и компилятор на самом деле представляют собой две разные программы, каждая из которых имеет свой синтаксис. Можно с легкостью объединить препроцессор с другими языками (на самом деле я делал это раньше, используя cpp в программах dBase III и AutoLISP, поскольку в этих языках отсутствовал хороший механизм включения для констант). Как уже указывали другие, typedef следует синтаксису системы объявлений C, а #define - простое прямое объявление замены.

1 голос
/ 27 февраля 2011

Я не знаю, почему в отношении языковых решений, но способ определения типа имеет смысл для меня.

Спецификатор 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 является частью препроцессора, а не языка, поэтому она не связана с тем, как язык представляет определенные конструкции, и может использовать более естественный способ ее объявления.

0 голосов
/ 27 февраля 2011

Да, синтаксис typedef также немного сбивает меня с толку. Я предполагаю, что ваш вопрос скорее жалобный - C почти 40 лет, вы не ожидаете, что синтаксис typedef изменится, не так ли?

...