C中的typedef和#define是否相同?


Answers:


122

没有。

#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 */

3
在typedef之后stdfx,该类型的有效对象是指向接收int且不返回值的函数的指针。
2015年

1
为什么在函数指针的大小写作为参数的情况下#define失败?
Allahjane '16

2
@Allahjane:扩展成为void fx_def(void (*)(int) fx);; 正确的声明是void fx_def(void (*fx)(int));
pmg

5
仅当您准备放弃语法:时,函数指针才可与宏一起使用#define FX_TYPE(f) void (*f)(int)。然后,您将函数声明为:void fx_def(FX_TYPE(fx));
plafer

229

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

23

不,他们不一样。例如:

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

预处理后,该行扩展为

int* a, b;

希望您能看到问题所在;只会a有类型int *; b将被声明为纯格式int(因为*关联于声明符,而不是类型说明符)。

对比一下

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

在这种情况下,ab都将具有type 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

尝试使用预处理宏。


13

#define定义宏。
typedef定义类型。

现在说,这里有一些区别:

使用#define,您可以定义可在编译时使用的常量。常量可与#ifdef一起使用,以检查代码的编译方式,并根据编译参数对某些代码进行专门化处理。
您还可以使用#define声明微型查找和替换宏函数

typedef可用于为类型赋予别名(您可能也可以使用#define进行命名),但是由于#define常量具有查找和替换的性质,因此它更安全。
除此之外,您还可以使用带有typedef的正向声明,该声明允许您声明将要使用但尚未链接到正在写入的文件的类型。


查找并替换#define的性质是什么意思?,谢谢
Mohamed El Shenawy 2015年

1
这意味着在编译之前,预处理器将找到所有宏并将其替换为其原始语法
Prince Vijay Pratap

“可以使用typedef为类型赋予别名”,这对我解释了目的,谢谢。
Dave Voyles

8

预处理程序宏(“ #define”)是一种词法替换工具,称为“搜索并替换”。他们完全不了解编程语言,也不了解您要做什么。您可以将它们视为美化的复制/粘贴机制-有时候这很有用,但您应谨慎使用。

Typedef是一种C语言功能,可让您为类型创建别名。这对于使复杂的复合类型(例如结构和函数指针)可读和可处理(在C ++中甚至必须对type进行类型定义)中非常有用。

对于(3):在可能的情况下,您应该始终比预处理器宏更喜欢语言功能!因此,始终对类型使用typedefs,对常量使用常量值。这样,编译器实际上可以与您进行有意义的交互。请记住,编译器是您的朋友,因此您应该尽可能多地告诉它。预处理器宏通过向编译器隐藏语义来实现完全相反的操作。


您能否在C ++中告诉一个示例,您必须在其中键入type的类型?我对此很好奇。
jyz 2013年

@jyzuz:如果您希望成员函数返回一个函数指针数组,则可能会发生某些事情,或者类似的事情–如果您试图拼出类型,GCC实际上会说“您必须使用typedef”。
Kerrek SB 2013年

4

它们是非常不同的,尽管它们通常用于实现自定义数据类型(这是我所假设的所有问题)。

如pmg所述,#define在编译器看到代码之前由预处理器进行处理(就像剪切和粘贴操作一样),typedef并由编译器解释。

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

#define defType int
typedef int tdType

defType x;
tdType y;

在这里,编译器将变量x视为int,但将变量y视为称为“ tdType”的数据类型,该大小恰好与int相同。如果编写的函数带有defType类型的参数,则调用者可以传递一个普通的int值,而编译器将不知道它们之间的区别。如果该函数改为使用tdType类型的参数,则编译器将确保在函数调用期间使用了正确类型的变量。

而且,某些调试器具有处理typedefs 的能力,这比将所有自定义类型作为其基本基本类型列出(要#define使用替代类型)要有用得多。


2


。typedef是一个C关键字,它为类型创建别名。
#define是预处理程序指令,可在编译之前创建文本替换事件。当编译器获取代码时,原始的“ #defined”字不再存在。#define主要用于宏和全局常量。


2
这里使用“指针”一词可能会引起一些混乱。

同意 这就是为什么我回去并在MSDN上添加了指向typdef的链接-以防万一以后有人使用此问题来查找typedef是什么。但也许我应该改变这个词……
Travel Guy,

2

AFAIK,不。

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

#define是用于定义宏或常规模式替换的预处理程序指令。例如。#define MAX 100MAX用100 代替所有出现的


0

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

您可以使用其他类型说明符来扩展宏类型名,但不能使用类型定义的类型名进行扩展:

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

typedef int fruit;
unsigned fruit i;   // illegal

同样,typedef的名称为声明中的每个declator提供类型。

#define fruit int *
fruit apple, banana;

宏扩展后,第二行变为:

int *apple, banana;

苹果是一个整数的指针,而香蕉是一个整数。相比下。这样的typedef:

typedef char *fruit;
fruit apple, banana;

声明苹果和香蕉相同。前面的名称不同,但是它们都是指向char的指针。


-1

就像上面每个人都说的,它们并不相同。大多数答案表明typedef比更具优势#define。但是,我要加一个要点#define
当您的代码非常大,分散在许多文件中时,最好使用它#define;它有助于提高可读性-您只需对所有代码进行预处理,即可在其声明本身的位置查看变量的实际类型定义。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.