为什么 #define 和 typedef 操作数颠倒?

发布于 2024-10-19 11:26:21 字数 223 浏览 2 评论 0原文

以下定义 A替换B

#define A B

而这将 A 定义为 B 的别名>类型 B

typedef B A;

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

The following defines A to be replaced by B:

#define A B

Whereas this defines A to be an alias for the type B:

typedef B A;

Why ? Isn't this incoherent ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

倦话 2024-10-26 11:26:21

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

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

Simply put: consider the following variable declarations:

// 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*);

Then the typedefs make perfect sense:

// 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*);

Macros, on the other hand, can take on a function-style syntax:

#define A(B, C) B, C

A(1, 2) // expands out to 1, 2

So for macros, the "definition" coming after the "name" makes more sense.

(This applies to C++ too, by the way.)

柠北森屋 2024-10-26 11:26:21

是的,宏几乎是一团糟。

typedef 在该语言的大部分其余部分完成后很长一段时间才被添加到该语言中。它使用与存储类相同的语法:

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

它们将 xyz 定义为 int - - 区别在于xyint类型的对象,而z基本上是的别名code>int 本身。

因此,typedef 相当适合该语言,并且(像往常一样)预处理器才是真正的“奇怪的人”。同时,您可能会认为语言的其余部分也应该改变。仅举一个明显的例子,帕斯卡大致颠倒了事情的顺序:

type
    z = integer;

var
    x : integer;

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

Yes, macros are pretty much a mess.

typedef was added to the language quite a while after most of the rest of the language was complete. It uses the same syntax as a storage class:

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

These define x, y and z as all being int -- the difference is that x and y are objects of type int, and z is basically an alias for int itself.

As such, typedef fits with the language proper reasonably well, and it's (as usual) the preprocessor that's really the "odd man out." At the same time, you could argue that the rest of the language should change as well. Just for an obvious example, Pascal roughly reversed the order of things:

type
    z = integer;

var
    x : integer;

While it doesn't make a lot of difference for trivial examples, I think this is rather simpler to read, especially when you deal with more complex declarations. For better or worse, however, Pascal has (mostly) fallen out of favor, and newer languages like Java have retained this particular part of C syntax (i.e., the part of C they kept was the one thing most in need of being changed).

二智少女 2024-10-26 11:26:21

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

Because A in typedef can be multiple symbols, e.g. typedef int Integer, *PInteger;.
This is consistent with how variables are defined (int var, *pvar;).

百变从容 2024-10-26 11:26:21

从语言语法的角度来看,typedef 与 externstatic(*) 一起位于存储类说明符组中,因此 typedef 具有与那些相同的位置。它显然不属于这个组,但我猜它可能是最不被放错的地方。

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

Typedef is from a language syntax point of view in the storage class specifier group together with extern and static(*), and thus typedef has the same placement as those. It does not obviously belong to this group, but I guess it was probably where it was least mis-placed.

(*)
Storage class also includes auto and register, but nobody uses those any more.

花开雨落又逢春i 2024-10-26 11:26:21

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

I don't know why as far as the language decisions are concerned, but the way typedef is makes sense to me.

The typedef specifier is part of the language. It serves as a way to alias a type to some name. You could always inline what the type is in a variable declaration.

struct arr { int len; char *chars; } name;
struct arr another_name;

Using typedef mirrors this use except instead of declaring a variable to the type, you're declaring a name for the type.

typedef struct { int len; char *chars; } arr;
arr name;
arr another_name;

The #define directive is part of the preprocessor and not of the language so it isn't bound to the way the language represents certain constructs and can use the more natural way of declaring it.

一念一轮回 2024-10-26 11:26:21

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

Because the pre-processor and the compiler are in fact two different programs, each with its own syntax. One could combine the preprocessor with other languages with not too much difficulty (I actually did that in older times by using cpp on dBase III programs and on AutoLISP because these languages lacked a good include mechanism for constants).
As others have already pointed out, typedef follows the syntax of the declaration system of C and #define is a simple straight-forward declaration of substitution.

我的影子我的梦 2024-10-26 11:26:21

是的,typedef 语法也让我有点困惑。我认为你的问题更多的是抱怨 - C 已经快 40 岁了,你不希望 typedef 语法改变,是吗?

Yes, typedef syntax tends to throw me off a little as well. I assume that your question is more of a complaint - C is almost 40 years old, you do not expect the typedef syntax to change, do you?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文