Answers:
没有。
#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 */
void fx_def(void (*)(int) fx);
; 正确的声明是void fx_def(void (*fx)(int));
。
#define FX_TYPE(f) void (*f)(int)
。然后,您将函数声明为:void fx_def(FX_TYPE(fx));
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
不,他们不一样。例如:
#define INTPTR int*
...
INTPTR a, b;
预处理后,该行扩展为
int* a, b;
希望您能看到问题所在;只会a
有类型int *
; b
将被声明为纯格式int
(因为*
关联于声明符,而不是类型说明符)。
对比一下
typedef int *INTPTR;
...
INTPTR a, b;
在这种情况下,a
和b
都将具有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
尝试使用预处理宏。
现在说,这里有一些区别:
使用#define,您可以定义可在编译时使用的常量。常量可与#ifdef一起使用,以检查代码的编译方式,并根据编译参数对某些代码进行专门化处理。
您还可以使用#define声明微型查找和替换宏函数。
typedef可用于为类型赋予别名(您可能也可以使用#define进行命名),但是由于#define常量具有查找和替换的性质,因此它更安全。
除此之外,您还可以使用带有typedef的正向声明,该声明允许您声明将要使用但尚未链接到正在写入的文件的类型。
预处理程序宏(“ #define
”)是一种词法替换工具,称为“搜索并替换”。他们完全不了解编程语言,也不了解您要做什么。您可以将它们视为美化的复制/粘贴机制-有时候这很有用,但您应谨慎使用。
Typedef是一种C语言功能,可让您为类型创建别名。这对于使复杂的复合类型(例如结构和函数指针)可读和可处理(在C ++中甚至必须对type进行类型定义)中非常有用。
对于(3):在可能的情况下,您应该始终比预处理器宏更喜欢语言功能!因此,始终对类型使用typedefs,对常量使用常量值。这样,编译器实际上可以与您进行有意义的交互。请记住,编译器是您的朋友,因此您应该尽可能多地告诉它。预处理器宏通过向编译器隐藏语义来实现完全相反的操作。
它们是非常不同的,尽管它们通常用于实现自定义数据类型(这是我所假设的所有问题)。
如pmg所述,#define
在编译器看到代码之前由预处理器进行处理(就像剪切和粘贴操作一样),typedef
并由编译器解释。
主要区别之一(至少在定义数据类型时)是typedef
允许进行更具体的类型检查。例如,
#define defType int
typedef int tdType
defType x;
tdType y;
在这里,编译器将变量x视为int,但将变量y视为称为“ tdType”的数据类型,该大小恰好与int相同。如果编写的函数带有defType类型的参数,则调用者可以传递一个普通的int值,而编译器将不知道它们之间的区别。如果该函数改为使用tdType类型的参数,则编译器将确保在函数调用期间使用了正确类型的变量。
而且,某些调试器具有处理typedef
s 的能力,这比将所有自定义类型作为其基本基本类型列出(要#define
使用替代类型)要有用得多。
否
。typedef是一个C关键字,它为类型创建别名。
#define是预处理程序指令,可在编译之前创建文本替换事件。当编译器获取代码时,原始的“ #defined”字不再存在。#define主要用于宏和全局常量。
如上所述,#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的指针。
stdfx
,该类型的有效对象是指向接收int且不返回值的函数的指针。