【问题标题】:Are typedef and #define the same in c?c中的typedef和#define是否相同?
【发布时间】:2010-12-12 14:06:48
【问题描述】:

不知道typedef#define中是否相同?

【问题讨论】:

    标签: c c macros c-preprocessor typedef


    【解决方案1】:

    没有。

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

    【讨论】:

    • 在 typedef stdfx 之后,该类型的有效对象是指向接收 int 但不返回值的函数的指针。
    • 为什么在函数指针作为参数的情况下#define会失败?
    • @Allahjane:展开变成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));
    【解决方案2】:

    AFAIK,没有。

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 这里使用术语“指针”可能会导致一些混乱。
      • 同意。这就是为什么我回去并在 MSDN 上添加了一个指向 typdef 的链接——以防万一将来有人会使用这个问题来查找 typedef 是什么。但也许我应该改变那个词......
      【解决方案4】:

      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
      

      【讨论】:

        【解决方案5】:

        不,它们不一样。例如:

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

        预处理后,该行扩展为

        int* a, b;
        

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

        对比

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

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

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

        【讨论】:

          【解决方案6】:

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

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

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

          #define defType int
          typedef int tdType
          
          defType x;
          tdType y;
          

          在这里,编译器将变量 x 视为 int,但将变量 y 视为称为“tdType”的数据类型,它恰好与 int 大小相同。如果你编写了一个接受 defType 类型参数的函数,调用者可以传递一个普通的 int 并且编译器不会知道其中的区别。如果函数取而代之的是 tdType 类型的参数,编译器将确保在函数调用期间使用正确类型的变量。

          此外,一些调试器能够处理 typedefs,这比将所有自定义类型列为其底层原始类型(就像使用 #define 代替时一样)要有用得多。

          【讨论】:

            【解决方案7】:

            预处理器宏(“#define's”)是一种词法替换工具,类似于“搜索和替换”。他们完全不了解编程语言,也不了解您要做什么。您可以将它们视为一种美化的复制/粘贴机制——有时这很有用,但您应该小心使用它。

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

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

            【讨论】:

            • 你能告诉一个例子在 C++ 中你必须 typedef 一个类型吗?我只是对此感到好奇。
            • @jyzuz:如果你想让一个成员函数返回一个函数指针数组,或者类似的东西——如果你试图拼出类型,GCC 实际上说“你必须使用类型定义”。
            【解决方案8】:

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

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

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

            typedef 可用于为类型提供别名(您也可以使用 #define 来做),但由于查找和替换,它更安全#define 常量的性质。
            除此之外,您可以将 forward declarationtypedef 一起使用,这允许您声明将使用但尚未链接到您正在编写的文件的类型在。

            【讨论】:

            • 查找和替换 #define 的性质是什么意思? ,谢谢
            • 这意味着在编译之前,预处理器会找到所有的宏并用它们原来的语法替换它们
            • "typedef 可用于为类型提供别名" 这解释了我的目的,谢谢。
            【解决方案9】:

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

            【讨论】:

              【解决方案10】:

              如上所述,#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的指针。

              【讨论】:

                猜你喜欢
                • 2017-04-23
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多