typedef只是代码中的字符串替换或其他东西吗?

时间:2010-07-16 08:47:00

标签: c++ c syntax

我很想知道typedef究竟是如何工作的。

typedef struct example identifier;

identifier x;

在上面的语句中,'identifier'被代码中的'struct example'替换(像字符串替换这样的东西)?如果不是,typedef在这做什么?

请指教!

8 个答案:

答案 0 :(得分:32)

不,它不是字符串替换 - 这将是宏。它为该类型创建了一个别名。

typedefs are preferred over macros用于自定义类型,部分原因是它们可以正确编码指针类型。

typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;
  

s1,s2和s3都被声明为char *,但s4被声明为char,这可能不是意图。

答案 1 :(得分:9)

typedef为类型引入了同义词。它不是普通的字符串替换,如下所示:

typedef int* int_ptr;
const int* a;    // pointer to const int
const int_ptr b; // const pointer to int

编译器也知道它是一个类型名称,你不能只是把它放在不允许类型而不会出现编译器错误的地方。

答案 2 :(得分:5)

所有人都同意,它不是类型替换,并且它比指针进入混合时要好得多,但还有其他细微之处。特别是使用typedef会影响代码的解析方式和程序的有效性。

在C和C ++中,用户定义的标识符都保存在不同的名称空间中(不是在C ++意义上,而是某种标识符空间)。当您使用typedef关键字时,为全局名称空间中的类型创建别名,其中包含函数。

// C/C++
struct test {};
void test( struct test x ) {} // ok, no collision

// C/C++
typedef struct test {} test; // test is now both in types and global spaces
//void test() {}       // compiler error: test is a typedef, cannot be redefined

这里的一个细微差别是,在C ++中,编译器将首先查看全局名称空间,如果没有找到它,它也会查看类型名称空间:

// C
struct test {};
//void f( test t );      // error, test is not defined in the global namespace
void f( struct test t ); // ok, we are telling the compiler where to look

// C++
struct test {};
void f( test t );        // ok, no test defined in the global name space, 
                         // the compiler looks in the types name space
void g( struct test t ); // also ok, even if 'struct' not needed here.

但这并不意味着合并了两个名称空间,只是查找将在两个地方进行搜索。

答案 3 :(得分:2)

一个重要的区别是typedef具有范围

以下是一个常见的习语

class Foo: public Bar 
{
  private:
   typedef Bar inherited;

  public:
    Foo(int x) : inherited(x) {};  // preferred to 'Bar(x)' 
}

通常你会在.cpp文件中使用构造函数定义,并在头文件中使用声明。如果您使用Foo(int x) : Bar(x),如果您更改类层次结构(例如Foo-> Wibble-> Bar而不是Foo-> Bar),则很有可能忘记更新构造函数。我个人建议将'inherited'typedef添加到每个子类。

请点击此处了解详情:Using "super" in C++

答案 4 :(得分:0)

Typedef是一种为(通常是复杂的)类型创建新名称的快捷方式。它的目的是比预处理器的字符串替换更窄。因此,它比预处理器定义(递归解析)更不容易出错。

答案 5 :(得分:0)

使用typedef可以创建别名。编译器用正确的代码替换别名。

如果你写:

typedef int company_id;
company_id mycompany = 100;

编译器得到:

int mycompany = 100;

答案 6 :(得分:0)

宏由预处理器完成,纯粹基于文本替换。因此,你可以说他们非常愚蠢。预处理器几乎可以接受任何垃圾而无需任何语法检查。

Typedef由编译器本身完成,它们通过添加您定义的派生类型来操作编译器自己的类型表。这需要完整的语法检查,以及专门针对类型的机制。

您可以认为编译器在声明struct时执行类似的“工作”。那里有一个定义,编译器将其转换为类型列表中的类型。

答案 7 :(得分:0)

我发现typedef使函数签名更容易阅读。假设您要返回指向二维数组的指针。这是可读的方式:

typedef int three_by_three[3][3];

three_by_three* foo();

以下是没有typedef的方法:

int (*bar())[3][3];

请注意,此签名看起来并不像应用了“字符串替换”的第一个版本。

如果C声明符语法不那么难看(Stroustrup:“我认为C声明符语法是一个失败的实验”),那么typedefs可能不会像现在这样使用它们。