Typedef

在C和C++编程语言中，typedef是一个关键字。它用来对一个数据类型取一个别名，目的是为了使源代码更易于阅读和理解。它通常用于简化声明复杂的类型组成的结构，但它也常常在各种长度的整数数据类型中看到，例如size_t和time_t。

语法

typedef的语法是 : typedef typedeclaration;

创建 Length 作为 int 的别名 : 
typedef int Length;
创建 PFI 作为一个指向"一个拥有两个char * 当作参数并回传int 的函数" 的指针的别名
typedef int (*PFI)(char *, char *);

创建一个具有特别意义的数据类型

typedef会被用来指定一种数据类型的意义。
例如 :  以下示范一个普通的声明，速度及分数都被声明为int
int current_speed ; 
int high_score ; 

void congratulate(int your_score) 
{ 
    if (your_score > high_score) 
        ...
通过typedef来指定新的数据类型的意义:
typedef int km_per_hour ;typedef int points ;km_per_hour current_speed ;  //"km_per_hour" is synonymous with "int" here,points high_score ;          //and thus, the compiler treats our new variables as integers.void congratulate(points your_score) {
    if (your_score > high_score)
        ...
前面两段代码运作状况一样，但是使用typedef的第二段代码更清楚的表示了两个变量(score和speed)，虽然数据类型都是int，却是各自代表不同的意义，且他们的数据并不兼容。
但请注意，其清楚的表示不同意义只是对于工程师而言，C/C++的编译器认为两个变量都是int时，并不会显示警告或错误，如: 以下代码，使用声明为速度的变量作为congratulate函数的参数 : 
void foo() 
{ 
    km_per_hour km100 = 100; 
    congratulate(km100);

但是，虽然在上面的代码中，编译器认为"km_per_hour"等于int，但在使用前缀unsigned, long, signed时，两者并不能互换使用。
void foo() {
    unsigned int a;         // Okay
    unsigned km_per_hour b; // Compiler complains
    long int c;             // Okay
    long km_per_hour d;     // Compiler complains
另一个例子：
int coxes;int jaffa;...coxes++;...if (jaffa == 10)...
现在来看以下代码：

 
typedef int Apple;typedef int Orange;Apple coxes;Orange jaffa;...coxes++;...if (jaffa == 10)...
这两段代码都做同样的一件事。第二个例子使用了typedef，使其更易于了解将要进行什么。也就是一个变量包含关于苹果的信息，而另一个包含关于橘子的信息。

简化声明语法

struct var {
    int data1;
    int data2;
    char data3;};
此处用户定义一个数据类型var。
像这样创建一个var 类型的变量，代码必须写为（注意，在 C++ 中声明一个struct 时，同时也隐含了typedef，C 则没有）：
struct var a;

在例子的最末处加入一行语句：

 
typedef struct var newtype;
现在要创建类型var 的变量时，代码可以写为：
newtype a;
这样就更容易阅读了，因为不用再为每一个var 类型的变量加上关键字struct。

也可以给数组使用typedef 声明。
typedef BaseType NewType [arrSize];
这样就可以在声明一个BaseType 类型和arrSize 大小的新数组时，将代码写为：
NewType array;

与数组一起使用

typedef可以简单的跟数组一起使用。例如 : 
typedef char arrType[6];    // type name: arrType
                            // new type: char[6]arrType arr={1,2,3,4,5,6};  // same as: char arr[6]={1,2,3,4,5,6}arrType *pArr;              // same as: char (*pArr)[6];
在这里，arrType是char[6]的别称。而arrType *pArr;则表示pArr是一个指向存储char[6]类型存储器的指针。

与指针一起使用

可以使用typedef来定义一个新的指针类型 : 
typedef int *intptr;   // type name: intptr
                       // new type: int*intptr ptr;            // same as: int *ptr
在上面那段代码中，intptr是一个 指针类型int*的 新的别名。intptr ptr;声明了一个变量(ptr)，其数据类型是int*。如此一来ptr就是一个 可以指向一段存储int数据的存储器 的指针了。
使用typedef来定义一个新的指针类型有时候会造成一些困惑 : 
typedef int *intptr;intptr cliff, allen;        // both cliff and allen are int* typeintptr cliff2, *allen2;     // cliff2 is int* type, but allen2 is int** type
                            // same as: intptr cliff2;
                            //          intptr *allen2;
在上面的代码中,ntptr cliff, allen;表示声明两个变量，其数据类型是int*，而intptr *allan2则使allen2的类型成为int**

与结构指针一起使用

Typedef可以跟结构体指针一起使用。如下 : 
struct Node {
    int data;
    struct Node *nextptr;};
使用typedef可以改写成如下 : 
typedef struct Node Node;struct Node {
    int data;
    Node *nextptr;};
在C语言中，可以在一行中声明复数的变量，不管其是不是指针。不管如何，如果你要声明指针，必须在每个变量前面加上星号。
在下面的代码中，工程师可能会以为errptr是一个指针，这个能会引起一些错误。
struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;
如果你用typedef定义一个Node *，这可以保证所有的变量都是一个指向一个structure type的指针。
typedef struct Node* NodePtr;...NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;

与函数指针一起使用

先看看以下这段尚未使用typedef的代码：
int do_math(float arg1, int arg2) {
    return arg2;}int call_a_func(int (*call_this)(float, int)) {
    int output = call_this(5.5, 7);
    return output;}int final_result = call_a_func(&do_math);
这段代码可以被改写成如下：
typedef int (*MathFunc)(float, int);int do_math(float arg1, int arg2) {
    return arg2;}int call_a_func(MathFunc call_this) {
    int output = call_this(5.5, 7);
    return output;}int final_result = call_a_func(&do_math);
在这里，MathFunc是一个指针，指向一个回传int并以一个float和一个int作为参数使用的函数。当一个函数被当作参数使用时，如果少了typedef它可能会变得难以了解。
以下是signal(3)(来自FreeBSD)的函数原型：
void (*signal(int sig, void (*func)(int)))(int);
上面声明的函数相当的神秘，因为它没有清楚的显示它以什么函数当作参数，或回传了什么数据类型。一个初心者工程师甚至可能以为它接收一个int作为参数，并不回传任何东西。但它其实接收了一个int和一个function pointer作为参数，并回传了一个function pointer。它可以被改写成以下代码：
typedef void (*sighandler_t)(int);sighandler_t signal(int sig, sighandler_t func);

用来类型转换

typedef同时可以用来类型转换。例如：
typedef int (*funcptr)(double);         // pointer to function taking a double returning intfuncptr x = (funcptr) NULL;             // C or C++funcptr y = funcptr(NULL);              // C++ onlyfuncptr z = static_cast<funcptr>(NULL); // C++ only
左侧，funcptr用来声明变量；右侧，funcptr则用来转换值的类型。
如果少了typedef，替换使用声明语法和类型转换语法是几乎不能做到的。例如：
void *p = NULL;int (*x)(double)  = (int (*)(double)) p; // This is legalint (*)(double) y = (int (*)(double)) p; // Left-hand side is not legalint (*z)(double)  = (int (*p)(double));  // Right-hand side is not legal