【发布时间】:2010-12-12 14:06:48
【问题描述】:
不知道typedef和#define在c中是否相同?
【问题讨论】:
标签: c c macros c-preprocessor typedef
不知道typedef和#define在c中是否相同?
【问题讨论】:
标签: c c macros c-preprocessor typedef
没有。
#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 */
【讨论】:
stdfx 之后,该类型的有效对象是指向接收 int 但不返回值的函数的指针。
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));
AFAIK,没有。
typedef 帮助您为现有数据类型设置“别名”。例如。 typedef char chr;
#define 是一个预处理器 指令,用于定义宏或一般模式替换。例如。 #define MAX 100,将所有出现的 MAX 替换为 100
【讨论】:
没有。
typedef 是为类型创建别名的 C 关键字。
#define 是预处理器指令,在编译之前创建文本替换事件。当编译器得到代码时,原来的“#defined”字已经不存在了。 #define 主要用于宏和全局常量。
【讨论】:
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 都将具有 int * 类型。
有些类型定义无法用预处理器宏模拟,例如指向函数或数组的指针:
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
尝试使用预处理器宏来执行此操作。
【讨论】:
它们非常不同,尽管它们通常用于实现自定义数据类型(这就是我假设这个问题的全部内容)。
正如 pmg 提到的,#define 在编译器看到代码之前由预处理器处理(如剪切和粘贴操作),而typedef 由编译器解释。
主要区别之一(至少在定义数据类型时)是typedef 允许进行更具体的类型检查。例如,
#define defType int
typedef int tdType
defType x;
tdType y;
在这里,编译器将变量 x 视为 int,但将变量 y 视为称为“tdType”的数据类型,它恰好与 int 大小相同。如果你编写了一个接受 defType 类型参数的函数,调用者可以传递一个普通的 int 并且编译器不会知道其中的区别。如果函数取而代之的是 tdType 类型的参数,编译器将确保在函数调用期间使用正确类型的变量。
此外,一些调试器能够处理 typedefs,这比将所有自定义类型列为其底层原始类型(就像使用 #define 代替时一样)要有用得多。
【讨论】:
预处理器宏(“#define's”)是一种词法替换工具,类似于“搜索和替换”。他们完全不了解编程语言,也不了解您要做什么。您可以将它们视为一种美化的复制/粘贴机制——有时这很有用,但您应该小心使用它。
Typedefs 是一种 C 语言功能,可让您为类型创建别名。这对于使复杂的复合类型(如结构和函数指针)具有可读性和可处理性非常有用(在 C++ 中,甚至在某些情况下您必须 typedef 一个类型)。
对于 (3):如果可能,您应该始终更喜欢语言功能而不是预处理器宏!所以总是对类型使用 typedefs,对常量使用常量值。这样,编译器实际上可以与您进行有意义的交互。请记住,编译器是你的朋友,所以你应该尽可能多地告诉它。预处理器宏通过隐藏编译器的语义来做完全相反的事情。
【讨论】:
现在说,这里有一些不同之处:
使用#define,您可以定义可在编译时使用的常量。常量可以与#ifdef一起使用来检查代码是如何编译的,并根据编译参数专门化某些代码。
您还可以使用 #define 声明微型查找和替换 Macro functions。
typedef 可用于为类型提供别名(您也可以使用 #define 来做),但由于查找和替换,它更安全#define 常量的性质。
除此之外,您可以将 forward declaration 与 typedef 一起使用,这允许您声明将使用但尚未链接到您正在编写的文件的类型在。
【讨论】:
正如上面每个人所说,它们并不相同。大多数答案表明typedef 比#define 更有优势。
但是让我给#define 加分:
当您的代码非常大,分散在许多文件中时,最好使用#define;它有助于提高可读性 - 您可以简单地预处理所有代码,以在变量声明本身的位置查看变量的实际类型定义。
【讨论】:
如上所述,#define 和 typedef 之间有一个关键区别。考虑这一点的正确方法是将 typedef 视为完整的“封装”类型。就是声明了之后就不能再添加了。
您可以使用其他类型说明符扩展宏类型名,但不能使用 typedef 的类型名:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
此外,typedef 的名称为声明中的每个 delator 提供类型。
#define fruit int *
fruit apple, banana;
宏展开后,第二行变成:
int *apple, banana;
Apple 是一个指向 int 的指针,而banana 是一个 int。相比下。像这样的 typedef:
typedef char *fruit;
fruit apple, banana;
声明苹果和香蕉是相同的。前面的名字不同,但都是指向char的指针。
【讨论】: