C 语言中 typedef 和#define 一样吗?

发布于 2024-08-09 14:19:39 字数 70 浏览 3 评论 0原文

我想知道C中的typedef#define是否相同。它们之间有什么区别?

I wonder if typedef and #define are the same in C. What are the differences between them?

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

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

发布评论

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

评论(11

送你一个梦 2024-08-16 14:19:39

typedef 就像变量一样遵守作用域规则,而 define 一直有效,直到编译单元结束(或直到匹配的 undef)。

另外,有些事情可以用 typedef 完成,而用 define 无法完成。
例如:

typedef int* int_p1;
int_p1 a, b, c;  // a, b, c are all int pointers

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer, because int_p2
                 // is replaced with int*, producing: int* a, b, c
                 // which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c;  // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp;  // func_p is a pointer to a function that
            // takes an int and returns an int

typedef obeys scoping rules just like variables, whereas define stays valid until the end of the compilation unit (or until a matching undef).

Also, some things can be done with typedef that cannot be done with define.
For example:

typedef int* int_p1;
int_p1 a, b, c;  // a, b, c are all int pointers

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer, because int_p2
                 // is replaced with int*, producing: int* a, b, c
                 // which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c;  // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp;  // func_p is a pointer to a function that
            // takes an int and returns an int
∞琼窗梦回ˉ 2024-08-16 14:19:39

不。

#define 是一个预处理器标记:编译器本身永远不会看到它。
typedef 是一个编译器标记:预处理器不关心它。

您可以使用其中一种来达到相同的效果,但最好使用适合您需求的工具。

#define MY_TYPE int
typedef int My_Type;

当事情变得“棘手”时,使用正确的工具就能解决问题

#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);

void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */

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

#define MY_TYPE int
typedef int My_Type;

When things get "hairy", using the proper tool makes it right

#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);

void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
白鸥掠海 2024-08-16 14:19:39

不,它们不一样。例如:

#define INTPTR int*
...
INTPTR a, b;

预处理后,该行扩展为

int* a, b;

希望您看到问题;只有 a 的类型为 int *b 将被声明为普通的 int (因为 * 与声明符相关联,而不是与类型说明符相关联)。

对比一下,

typedef int *INTPTR;
...
INTPTR a, b;

在本例中,ab 的类型均为 int *

有一些 typedef 的整个类无法用预处理器宏来模拟,例如指向函数或数组的指针:

typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20]; 
...
CALLBACK aCallbackFunc;        // aCallbackFunc is a pointer to a function 
                               // returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
                               // returning a pointer to a 20-element array
                               // of pointers to int

尝试使用预处理器宏来实现这一点。

No, they are not the same. For example:

#define INTPTR int*
...
INTPTR a, b;

After preprocessing, that line expands to

int* a, b;

Hopefully you see the problem; only a will have the type int *; b will be declared a plain int (because the * is associated with the declarator, not the type specifier).

Contrast that with

typedef int *INTPTR;
...
INTPTR a, b;

In this case, both a and b will have type int *.

There are whole classes of typedefs that cannot be emulated with a preprocessor macro, such as pointers to functions or arrays:

typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20]; 
...
CALLBACK aCallbackFunc;        // aCallbackFunc is a pointer to a function 
                               // returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
                               // returning a pointer to a 20-element array
                               // of pointers to int

Try doing that with a preprocessor macro.

未央 2024-08-16 14:19:39

#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.

生死何惧 2024-08-16 14:19:39

预处理器宏(“#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.

鹿港小镇 2024-08-16 14:19:39

尽管它们经常用于实现自定义数据类型(这就是我假设这个问题的全部内容),但它们非常不同。

正如 pmg 提到的,#define 在编译器看到代码之前由预处理器处理(就像剪切和粘贴操作),而 typedef 由编译器。

主要区别之一(至少在定义数据类型时)是 typedef 允许进行更具体的类型检查。例如,

#define defType int
typedef int tdType

defType x;
tdType y;

这里,编译器将变量 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, and typedef 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,

#define defType int
typedef int tdType

defType x;
tdType y;

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 typedefs, 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).

情深缘浅 2024-08-16 14:19:39

否。
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.

真心难拥有 2024-08-16 14:19:39

AFAIK,不。

typedef 可帮助您为现有数据类型设置“别名”。例如。 typedef char chr;

#define 是一个预处理器指令,用于定义宏或一般模式替换。例如。 #define MAX 100,将所有出现的 MAX 替换为 100

AFAIK, 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 of MAX with 100

孤星 2024-08-16 14:19:39

如上所述,#define 和 typedef 之间存在关键区别。正确的思考方式是将 typedef 视为完整的“封装”类型。这意味着您声明后无法添加。

您可以使用其他类型说明符扩展宏类型名,但不能使用 typedef 的类型名:

#define fruit int
unsigned fruit i;   // works fine

typedef int fruit;
unsigned fruit i;   // illegal

此外,typedef 的名称为声明中的每个声明符提供类型。

#define fruit int *
fruit apple, banana;

宏展开后,第二行变为:

int *apple, banana;

Apple 是一个指向 int 的指针,而 Banana 是一个 int 。相比之下。像这样的 typedef:

typedef char *fruit;
fruit apple, banana;

声明苹果和香蕉是相同的。前面的名字不同,但都是指向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:

#define fruit int
unsigned fruit i;   // works fine

typedef int fruit;
unsigned fruit i;   // illegal

Also, a typedef'd name provides the type for every declator in a declaration.

#define fruit int *
fruit apple, banana;

After macro expansion, the second line becomes:

int *apple, banana;

Apple is a pointer to an int, while banana is an int. In comparison. a typedef like this:

typedef char *fruit;
fruit apple, banana;

declares both apple and banana to be the same. The name on the front is different, but they are both pointers to a char.

ㄖ落Θ余辉 2024-08-16 14:19:39

使用 typedef 的另一个原因(在其他答案中仅简要提到过,但我认为这是创建 typedef 的全部原因)是在使用具有自定义类型的库时使调试更容易。例如,我将使用类型转换错误。下面的两个代码都会打印一个编译时错误,指出 char 无法与字符串进行比较,但方式不同。

typedef char letter;
letter el = 'e';
if(el == "hello");

上面的代码将打印类似 the variable "el" of type letter (aka "char") is not compatable with type "char*"

#define letter char
letter el = 'e';
if(el == "hello");

此代码将打印 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.

typedef char letter;
letter el = 'e';
if(el == "hello");

The above code will print something like the variable "el" of type letter (aka "char") is not compatable with type "char*"

#define letter char
letter el = 'e';
if(el == "hello");

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.

笑梦风尘 2024-08-16 14:19:39

正如楼上各位所说,它们并不相同。大多数答案表明 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.

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