我很想知道typedef究竟是如何工作的。
typedef struct example identifier;
identifier x;
在上面的语句中,'identifier'被代码中的'struct example'替换(像字符串替换这样的东西)?如果不是,typedef在这做什么?
请指教!答案 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可能不会像现在这样使用它们。