C 语言中 typedef 和#define 一样吗?
我想知道C中的typedef
和#define
是否相同。它们之间有什么区别?
I wonder if typedef
and #define
are the same in C. What are the differences between them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
typedef
就像变量一样遵守作用域规则,而define
一直有效,直到编译单元结束(或直到匹配的undef
)。另外,有些事情可以用
typedef
完成,而用define
无法完成。例如:
typedef
obeys scoping rules just like variables, whereasdefine
stays valid until the end of the compilation unit (or until a matchingundef
).Also, some things can be done with
typedef
that cannot be done withdefine
.For example:
不。
#define
是一个预处理器标记:编译器本身永远不会看到它。typedef
是一个编译器标记:预处理器不关心它。您可以使用其中一种来达到相同的效果,但最好使用适合您需求的工具。
当事情变得“棘手”时,使用正确的工具就能解决问题
No.
#define
is a preprocessor token: the compiler itself will never see it.typedef
is a compiler token: the preprocessor does not care about it.You can use one or the other to achieve the same effect, but it's better to use the proper one for your needs
When things get "hairy", using the proper tool makes it right
不,它们不一样。例如:
预处理后,该行扩展为
希望您看到问题;只有
a
的类型为int *
;b
将被声明为普通的int
(因为*
与声明符相关联,而不是与类型说明符相关联)。对比一下,
在本例中,
a
和b
的类型均为int *
。有一些 typedef 的整个类无法用预处理器宏来模拟,例如指向函数或数组的指针:
尝试使用预处理器宏来实现这一点。
No, they are not the same. For example:
After preprocessing, that line expands to
Hopefully you see the problem; only
a
will have the typeint *
;b
will be declared a plainint
(because the*
is associated with the declarator, not the type specifier).Contrast that with
In this case, both
a
andb
will have typeint *
.There are whole classes of typedefs that cannot be emulated with a preprocessor macro, such as pointers to functions or arrays:
Try doing that with a preprocessor macro.
#define 定义宏。
typedef 定义类型。
现在说一下,这里有一些区别:
使用#define,您可以定义可在编译时使用的常量。这些常量可以与#ifdef一起使用来检查代码是如何编译的,并根据编译参数专门化某些代码。
您还可以使用 #define 声明微型查找和替换 宏函数。
typedef 可用于为类型提供别名(您也可以使用 #define 来实现),但由于 typedef 的查找和替换性质,它更安全。强>#define常量。
除此之外,您可以将前向声明与typedef<一起使用/strong> 它允许您声明将使用的类型,但尚未链接到您正在写入的文件。
#define defines macros.
typedef defines types.
Now saying that, here are a few differences:
With #define you can define constants that can be used in compile time. The constants can be used with #ifdef to check how the code is compiled, and specialize certain code according to compile parameters.
You can also use #define to declare miniature find-and-replace Macro functions.
typedef can be used to give aliases to types (which you could probably do with #define as well), but it's safer because of the find-and-replace nature of #define constants.
Besides that, you can use forward declaration with typedef which allows you to declare a type that will be used, but isn't yet linked to the file you're writing in.
预处理器宏(“
#define
's”)是一种词法替换工具,类似于“搜索和替换”。他们完全不了解编程语言,也不理解您想要做什么。您可以将它们视为一种美化的复制/粘贴机制——有时这很有用,但您应该小心使用它。Typedef 是一项 C 语言功能,可让您为类型创建别名。这对于使复杂的复合类型(如结构和函数指针)可读且可处理非常有用(在 C++ 中,甚至在某些情况下您必须 typedef 类型)。
对于 (3):如果可能的话,您应该始终更喜欢语言功能而不是预处理器宏!因此,始终对类型使用 typedef,对常量使用常量值。这样,编译器实际上可以与您进行有意义的交互。请记住,编译器是您的朋友,因此您应该尽可能多地告诉它。预处理器宏通过向编译器隐藏语义来执行完全相反的操作。
Preprocessor macros ("
#define
's") are a lexical replacement tool a la "search and replace". They are entirely agnostic of the programming language and have no understanding what you're trying to do. You can think of them as a glorified copy/paste mechanic -- occasionally that's useful, but you should use it with care.Typedefs are a C language feature that lets you create aliases for types. This is extremely useful to make complicated compound types (like structs and function pointers) readable and handlable (in C++ there are even situations where you must typedef a type).
For (3): You should always prefer language features over preprocessor macros when that's possible! So always use typedefs for types, and constant values for constants. That way, the compiler can actually interact with you meaningfully. Remember that the compiler is your friend, so you should tell it as much as possible. Preprocessor macros do the exact opposite by hiding your semantics from the compiler.
尽管它们经常用于实现自定义数据类型(这就是我假设这个问题的全部内容),但它们非常不同。
正如 pmg 提到的,
#define
在编译器看到代码之前由预处理器处理(就像剪切和粘贴操作),而typedef
由编译器。主要区别之一(至少在定义数据类型时)是 typedef 允许进行更具体的类型检查。例如,
这里,编译器将变量 x 视为 int,但将变量 y 视为名为“tdType”的数据类型,该数据类型恰好与 int 大小相同。如果您编写了一个采用 defType 类型参数的函数,调用者可以传递一个普通的 int,而编译器不会知道其中的区别。如果函数采用 tdType 类型的参数,编译器将确保在函数调用期间使用正确类型的变量。
此外,一些调试器能够处理
typedef
,这比将所有自定义类型列为其底层基元类型有用得多(就像#define
那样) > 被用来代替)。They are very different, although they are often used to implement custom data types (which is what I am assuming this question is all about).
As pmg mentioned,
#define
is handled by the pre-processor (like a cut-and-paste operation) before the compiler sees the code, andtypedef
is interpreted by the compiler.One of the main differences (at least when it comes to defining data types) is that
typedef
allows for more specific type checking. For example,Here, the compiler sees variable x as an int, but variable y as a data type called 'tdType' that happens to be the same size as an int. If you wrote a function that took a parameter of type defType, the caller could pass a normal int and the compiler wouldn't know the difference. If the function instead took a parameter of type tdType, the compiler would ensure that a variable of the proper type was used during function calls.
Also, some debuggers have the ability to handle
typedef
s, which can be much more useful than having all custom types listed as their underlying primitive types (as it would be if#define
was used instead).否。
typedef 是创建别名的 C 关键字对于类型。
#define 是一个预处理器指令,它在编译之前创建一个文本替换事件。当编译器到达代码时,原来的“#define”一词不再存在。 #define 主要用于宏和全局常量。
No.
typedef is a C keyword that creates an alias for a type.
#define is a pre-processor instruction, that creates a text replacement event prior to compilation. When the compiler gets to the code, the original "#defined" word is no longer there. #define is mostly used for macros and global constants.
AFAIK,不。
typedef
可帮助您为现有数据类型设置“别名”。例如。typedef char chr
;#define
是一个预处理器指令,用于定义宏或一般模式替换。例如。#define MAX 100
,将所有出现的MAX
替换为 100AFAIK, No.
typedef
helps you set up an "alias" to an existing data type. For eg.typedef char chr
;#define
is a preprocessor directive used to define macros or general pattern substitutions. For eg.#define MAX 100
, substitutes all occurrences ofMAX
with 100如上所述,#define 和 typedef 之间存在关键区别。正确的思考方式是将 typedef 视为完整的“封装”类型。这意味着您声明后无法添加。
您可以使用其他类型说明符扩展宏类型名,但不能使用 typedef 的类型名:
此外,typedef 的名称为声明中的每个声明符提供类型。
宏展开后,第二行变为:
Apple 是一个指向 int 的指针,而 Banana 是一个 int 。相比之下。像这样的 typedef:
声明苹果和香蕉是相同的。前面的名字不同,但都是指向char的指针。
As mentioned above, there is a key difference between
#define
and typedef. The right way to think about that is to view a typedef as being a complete "encapsulated" type. It means that you cannot add to it after you have declared it.You can extend a macro typename with other type specifiers, but not a typedef'd typename:
Also, a typedef'd name provides the type for every declator in a declaration.
After macro expansion, the second line becomes:
Apple is a pointer to an int, while banana is an int. In comparison. a typedef like this:
declares both apple and banana to be the same. The name on the front is different, but they are both pointers to a char.
使用 typedef 的另一个原因(在其他答案中仅简要提到过,但我认为这是创建 typedef 的全部原因)是在使用具有自定义类型的库时使调试更容易。例如,我将使用类型转换错误。下面的两个代码都会打印一个编译时错误,指出 char 无法与字符串进行比较,但方式不同。
上面的代码将打印类似
the variable "el" of type letter (aka "char") is not compatable with type "char*"
此代码将打印
the variable "el" char 类型与“char*”类型不兼容
这可能看起来很愚蠢,因为我将“letter”定义为“char”,但在更复杂的库中,这可能会非常令人困惑,因为指向按钮等对象的指针,窗口、声音服务器、图像和许多其他东西都被定义为
unsigned char *
,只有在使用 #define 方法时才可以进行调试。Another reason to use typedef (which has only been mentioned briefly in other answers and yet I think is the entire reason typedef was created) is to make debugging easier when using libraries that have custom types. For example, I'll use a type-conversion error. Both the codes below will print a compile-time error saying that a char is not comparable to a string, but in different ways.
The above code will print something like
the variable "el" of type letter (aka "char") is not compatable with type "char*"
This code will instead print
the variable "el" of type char is not compatable with type "char*"
This may seem silly because I'm defining "letter" as "char", but in more complex libraries this can be extremely confusing because pointers to objects like buttons, windows, sound servers, images, and lots of other things are defined as
unsigned char *
, which would only be debuggable as exactly that when using the #define method.正如楼上各位所说,它们并不相同。大多数答案表明
typedef
比#define
更有优势。但让我说一下
#define
的一个优点:当你的代码非常大,分散在许多文件中时,最好使用
#define
;它有助于提高可读性 - 您可以简单地预处理所有代码,以在变量声明本身的位置查看变量的实际类型定义。As everyone said above, they aren't the same. Most of the answers indicate
typedef
to be more advantageous than#define
.But let me put a plus point of
#define
:when your code is extremely big, scattered across many files, it's better to use
#define
; it helps in readability - you can simply preprocess all the code to see the actual type definition of a variable at the place of its declaration itself.