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

时间:2009-11-03 09:57:30

标签: c macros c-preprocessor typedef

我想知道typedef#define是否相同?

10 个答案:

答案 0 :(得分:210)

typedef遵守范围规则,就像变量一样,而define 保持有效直到文件结尾(或直到匹配的undef)。

此外,使用typedef无法完成某些事情。

示例:

define

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

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer!

typedef int a10[10];
a10 a, b, c; // create three 10-int arrays

答案 1 :(得分:108)

没有

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

答案 2 :(得分:21)

不,他们不一样。例如:

#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

尝试使用预处理器宏执行此操作。

答案 3 :(得分:12)

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

现在说,这里有一些不同之处:

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

typedef 可用于为类型提供别名(您可以使用 #define 执行此操作),但由于查找和替换它更安全 #define 常量的性质。
除此之外,您可以将 forward declaration typedef 一起使用,它允许您声明将要使用的类型,但尚未链接到您的文件重新写作。

答案 4 :(得分:5)

预处理器宏(“#define”)是词汇替换工具,“搜索和替换”。他们完全不了解编程语言,也不了解你想要做什么。您可以将它们视为一个美化的复制/粘贴机制 - 偶尔会有用,但您应该小心使用它。

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

For(3):在可能的情况下,你应该总是喜欢语言功能而不是预处理器宏!所以总是对类型使用typedef,对常量使用常量值。这样,编译器实际上可以与您进行有意义的交互。请记住编译器是你的朋友,所以你应该尽可能地告诉它。预处理器宏通过隐藏来自编译器的语义来完全相反。

答案 5 :(得分:3)

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

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

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

#define defType int
typedef int tdType

defType x;
tdType y;

这里,编译器将变量x视为int,而变量y视为名为'tdType'的数据类型,其大小与int相同。如果你编写了一个带有defType类型参数的函数,调用者可以传递一个普通的int,编译器也不会知道它的区别。如果函数改为使用tdType类型的参数,编译器将确保在函数调用期间使用了正确类型的变量。

此外,一些调试器具有处理typedef的能力,这比将所有自定义类型列为其基础原始类型(如果使用#define时更有用) )。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

AFAIK,没有。

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

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

替换MAX的所有出现

答案 8 :(得分:1)

如上所述,#define与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;

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

typedef char *fruit;
fruit apple, banana;

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

答案 9 :(得分:0)

正如上面所说的那样,它们并不相同。大多数答案表明#define#define更有利。 但是,让我加上#define的加分:当您的代码非常大,分散在许多文件中时,使用{{1}}会更好;它有助于提高可读性 - 您可以简单地预处理所有代码,以便在声明本身的位置查看变量的实际类型定义。