为什么#define和typedef操作数被反转?

时间:2011-02-27 20:25:25

标签: c typedef c-preprocessor

以下内容AB定义为替换 #define A B

A

这会将B定义为类型 typedef B A; 的别名:

{{1}}

为什么?这不是语无伦次吗?

7 个答案:

答案 0 :(得分:7)

简单地说:考虑以下变量声明:

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

答案 1 :(得分:4)

是的,宏非常混乱。

在语言的其余大部分内容完成后,

typedef被添加到语言中很长一段时间。它使用与存储类相同的语法:

static int x;
extern int y;
typedef int z;

这些定义xyz全部为int - 区别在于xy是键入intz基本上是int本身的别名。

因此,typedef恰当地适合于语言,而且(像往常一样)预处理器实际上是“奇怪的人”。与此同时,你可以争辩说其他语言也应该改变。仅举一个明显的例子,Pascal大致颠倒了事物的顺序:

type
    z = integer;

var
    x : integer;

虽然它对于琐碎的例子并没有太大的区别,但我认为这更容易阅读,特别是当你处理更复杂的声明时。然而,无论好坏,Pascal已经(大部分)失宠了,像Java这样的新语言保留了C语法的这一特定部分(即,他们保留的C部分是最需要改变的一部分)

答案 2 :(得分:2)

因为A中的typedef可以是多个符号,例如typedef int Integer, *PInteger;。 这与变量的定义方式(int var, *pvar;)一致。

答案 3 :(得分:2)

Typedef来自storage class specifier组中的语言语法观点以及externstatic(*),因此typedef具有与这些相同的位置。它显然不属于这个群体,但我想这可能是最不正确的地方。

(*) 存储类还包括autoregister,但没有人再使用它们。

答案 4 :(得分:1)

我不知道为什么就语言决定而言,但是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指令是预处理器的一部分,而不是语言的一部分,因此它不受语言表示某些结构的约束,并且可以使用更自然的方式来声明它。

答案 5 :(得分:1)

因为预处理器和编译器实际上是两个不同的程序,每个程序都有自己的语法。可以将预处理器与其他语言结合起来并没有太大的困难(我实际上在较旧的时候通过在dBase III程序和AutoLISP上使用cpp来实现这一点,因为这些语言缺乏良好的常量包含机制)。 正如其他人已经指出的那样,typedef遵循C的声明系统的语法,#define是一个简单的直接替换声明。

答案 6 :(得分:0)

是的,typedef语法往往会让我失望一点。我认为你的问题更多的是抱怨--C差不多40岁了,你不希望typedef语法改变,是吗?