I was curious to know how exactly typedef works.
我很想知道typedef究竟是如何工作的。
typedef struct example identifier;
identifier x;
In above statement is 'identifier' just replaced (somethings like string replacement) with 'struct example' in code? If no, what does typedef do here?
在上面的语句中,'identifier'只是在代码中用'struct example'替换(像字符串替换这样的东西)?如果不是,typedef在这做什么?
please enlighten!
8 个解决方案
#1
32
No, it is not a string replacement - that would be macros. It creates an alias for the type.
不,它不是字符串替换 - 这将是宏。它为类型创建别名。
typedefs are preferred over macros for custom types, in part because they can correctly encode pointer types.
typedef优先于自定义类型的宏,部分原因是它们可以正确编码指针类型。
typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;
s1, s2, and s3 are all declared as char *, but s4 is declared as a char, which is probably not the intention.
s1,s2和s3都声明为char *,但s4声明为char,这可能不是意图。
#2
9
A typedef
introduces a synonym for types. It isn't plain string replacement, as the following shows:
typedef引入了类型的同义词。它不是普通的字符串替换,如下所示:
typedef int* int_ptr;
const int* a; // pointer to const int
const int_ptr b; // const pointer to int
The compiler also is aware that it is a type name, you can't just put it somewhere where a type isn't allowed without getting a compiler error.
编译器也知道它是一个类型名称,你不能只是把它放在一个不允许类型的地方而不会出现编译器错误。
#3
5
All agree in that it is not type substitution, and that it is much better than it when pointers get into the mix, but there are also other subtleties. In particular the use of typedefs can affect how code is parsed and the validity of programs.
所有人都同意,它不是类型替换,并且它比指针进入混合时要好得多,但也有其他细微之处。特别是使用typedef会影响代码的解析方式和程序的有效性。
Both in C and in C++ user defined identifiers are kept in different name spaces (not in the C++ sense, but some kind of identifier-space). When you use the typedef keyword you make an alias for the type in the global name space, where functions reside.
在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
A slight difference here is that in C++ the compiler will first look in the global name space and if not found there it will also look in the types name space:
这里略有不同的是,在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.
But this does not mean that the two namespaces are merged, only that the lookup will search in both places.
但这并不意味着合并了两个名称空间,只是查找将在两个位置进行搜索。
#4
2
One important distinction is that typedef
s have scope.
一个重要的区别是typedef具有范围。
The following is a common idiom
以下是一个常见的习语
class Foo: public Bar
{
private:
typedef Bar inherited;
public:
Foo(int x) : inherited(x) {}; // preferred to 'Bar(x)'
}
Often you would have the constructor definition in a .cpp file, with the declaration in header. If you use Foo(int x) : Bar(x)
, there's a good chance you will forget to update the constructor if you change the class hierarchy such that Foo->Wibble->Bar instead of Foo->Bar. Personally I recommend adding the 'inherited' typedef to every subclass.
通常,您将在.cpp文件中使用构造函数定义,并在头文件中使用声明。如果使用Foo(int x):Bar(x),如果更改类层次结构(例如Foo-> Wibble-> Bar而不是Foo-> Bar),则很可能会忘记更新构造函数。我个人建议将'inherited'typedef添加到每个子类。
See here for more details: Using "super" in C++
有关更多详细信息,请参见此处:在C ++中使用“super”
#5
0
Typedef is a shortcut which creates new name for (usually complex) type. It's purpose is more narrow than preprocessor's string replacement. Thus, it is less error-prone than preprocessor definitions (which are parsed recursively).
Typedef是一种为(通常是复杂的)类型创建新名称的快捷方式。它的目的比预处理器的字符串替换更窄。因此,它比预处理器定义(递归解析)更不容易出错。
#6
0
With typedef you make an alias. The compiler replaces the alias with the correct code.
使用typedef,您可以创建别名。编译器用正确的代码替换别名。
If you write:
如果你写:
typedef int company_id;
company_id mycompany = 100;
The compilers gets:
编译器得到:
int mycompany = 100;
#7
0
Macros are done by the preprocessor and are purely based on text substitution. Thus, you could say they're pretty dumb. The preprocessor will accept pretty much any garbage without any syntax check.
宏由预处理器完成,纯粹基于文本替换。因此,你可以说他们非常愚蠢。预处理器几乎可以接受任何垃圾而无需任何语法检查。
Typedefs are done by the compiler itself and they manipulate the compiler's own type table by adding a derived type you define. This is subject to full syntax checking, and a mechanism specifically for types only.
Typedef由编译器本身完成,它们通过添加您定义的派生类型来操作编译器自己的类型表。这需要完整的语法检查,以及专门针对类型的机制。
You could think of the compiler doing similar "work" to when you declare a struct
. There's a definition there, and the compiler turns it into a type in its list of types.
您可以认为编译器在声明结构时执行类似的“工作”。那里有一个定义,编译器将其转换为类型列表中的类型。
#8
0
I find typedefs make function signatures a lot easier to read. Suppose you want to return a pointer to a two-dimensional array. Here is the readable way:
我发现typedef使函数签名更容易阅读。假设您要返回指向二维数组的指针。这是可读的方式:
typedef int three_by_three[3][3];
three_by_three* foo();
And here is how you can do it without a typedef:
以下是没有typedef的方法:
int (*bar())[3][3];
Note that this signature does does not look at all like the first version with a "string replacement" applied.
请注意,此签名看起来并不像应用了“字符串替换”的第一个版本。
If the C declarator syntax wasn't that ugly (Stroustrup: "I consider the C declarator syntax an experiment that failed"), typedefs probably wouldn't by used as much as they are now.
如果C声明符语法不那么难看(Stroustrup:“我认为C声明符语法是一个失败的实验”),那么typedef可能不会像现在这样使用它们。
#1
32
No, it is not a string replacement - that would be macros. It creates an alias for the type.
不,它不是字符串替换 - 这将是宏。它为类型创建别名。
typedefs are preferred over macros for custom types, in part because they can correctly encode pointer types.
typedef优先于自定义类型的宏,部分原因是它们可以正确编码指针类型。
typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;
s1, s2, and s3 are all declared as char *, but s4 is declared as a char, which is probably not the intention.
s1,s2和s3都声明为char *,但s4声明为char,这可能不是意图。
#2
9
A typedef
introduces a synonym for types. It isn't plain string replacement, as the following shows:
typedef引入了类型的同义词。它不是普通的字符串替换,如下所示:
typedef int* int_ptr;
const int* a; // pointer to const int
const int_ptr b; // const pointer to int
The compiler also is aware that it is a type name, you can't just put it somewhere where a type isn't allowed without getting a compiler error.
编译器也知道它是一个类型名称,你不能只是把它放在一个不允许类型的地方而不会出现编译器错误。
#3
5
All agree in that it is not type substitution, and that it is much better than it when pointers get into the mix, but there are also other subtleties. In particular the use of typedefs can affect how code is parsed and the validity of programs.
所有人都同意,它不是类型替换,并且它比指针进入混合时要好得多,但也有其他细微之处。特别是使用typedef会影响代码的解析方式和程序的有效性。
Both in C and in C++ user defined identifiers are kept in different name spaces (not in the C++ sense, but some kind of identifier-space). When you use the typedef keyword you make an alias for the type in the global name space, where functions reside.
在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
A slight difference here is that in C++ the compiler will first look in the global name space and if not found there it will also look in the types name space:
这里略有不同的是,在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.
But this does not mean that the two namespaces are merged, only that the lookup will search in both places.
但这并不意味着合并了两个名称空间,只是查找将在两个位置进行搜索。
#4
2
One important distinction is that typedef
s have scope.
一个重要的区别是typedef具有范围。
The following is a common idiom
以下是一个常见的习语
class Foo: public Bar
{
private:
typedef Bar inherited;
public:
Foo(int x) : inherited(x) {}; // preferred to 'Bar(x)'
}
Often you would have the constructor definition in a .cpp file, with the declaration in header. If you use Foo(int x) : Bar(x)
, there's a good chance you will forget to update the constructor if you change the class hierarchy such that Foo->Wibble->Bar instead of Foo->Bar. Personally I recommend adding the 'inherited' typedef to every subclass.
通常,您将在.cpp文件中使用构造函数定义,并在头文件中使用声明。如果使用Foo(int x):Bar(x),如果更改类层次结构(例如Foo-> Wibble-> Bar而不是Foo-> Bar),则很可能会忘记更新构造函数。我个人建议将'inherited'typedef添加到每个子类。
See here for more details: Using "super" in C++
有关更多详细信息,请参见此处:在C ++中使用“super”
#5
0
Typedef is a shortcut which creates new name for (usually complex) type. It's purpose is more narrow than preprocessor's string replacement. Thus, it is less error-prone than preprocessor definitions (which are parsed recursively).
Typedef是一种为(通常是复杂的)类型创建新名称的快捷方式。它的目的比预处理器的字符串替换更窄。因此,它比预处理器定义(递归解析)更不容易出错。
#6
0
With typedef you make an alias. The compiler replaces the alias with the correct code.
使用typedef,您可以创建别名。编译器用正确的代码替换别名。
If you write:
如果你写:
typedef int company_id;
company_id mycompany = 100;
The compilers gets:
编译器得到:
int mycompany = 100;
#7
0
Macros are done by the preprocessor and are purely based on text substitution. Thus, you could say they're pretty dumb. The preprocessor will accept pretty much any garbage without any syntax check.
宏由预处理器完成,纯粹基于文本替换。因此,你可以说他们非常愚蠢。预处理器几乎可以接受任何垃圾而无需任何语法检查。
Typedefs are done by the compiler itself and they manipulate the compiler's own type table by adding a derived type you define. This is subject to full syntax checking, and a mechanism specifically for types only.
Typedef由编译器本身完成,它们通过添加您定义的派生类型来操作编译器自己的类型表。这需要完整的语法检查,以及专门针对类型的机制。
You could think of the compiler doing similar "work" to when you declare a struct
. There's a definition there, and the compiler turns it into a type in its list of types.
您可以认为编译器在声明结构时执行类似的“工作”。那里有一个定义,编译器将其转换为类型列表中的类型。
#8
0
I find typedefs make function signatures a lot easier to read. Suppose you want to return a pointer to a two-dimensional array. Here is the readable way:
我发现typedef使函数签名更容易阅读。假设您要返回指向二维数组的指针。这是可读的方式:
typedef int three_by_three[3][3];
three_by_three* foo();
And here is how you can do it without a typedef:
以下是没有typedef的方法:
int (*bar())[3][3];
Note that this signature does does not look at all like the first version with a "string replacement" applied.
请注意,此签名看起来并不像应用了“字符串替换”的第一个版本。
If the C declarator syntax wasn't that ugly (Stroustrup: "I consider the C declarator syntax an experiment that failed"), typedefs probably wouldn't by used as much as they are now.
如果C声明符语法不那么难看(Stroustrup:“我认为C声明符语法是一个失败的实验”),那么typedef可能不会像现在这样使用它们。