typedef 的作用是什么?

60

在C语言中,typedef关键字有什么用途?它何时需要使用?

8个回答

60

typedef是用来将某个东西定义为类型的。例如:

typedef struct {
  int a;
  int b;
} THINGY;

...将THINGY定义为给定的结构体。这样,您可以像这样使用它:

THINGY t;

...而不是:

struct _THINGY_STRUCT {
  int a;
  int b;
};

struct _THINGY_STRUCT t;

这段文字有些啰嗦。typedef可以使一些事情变得非常清晰,尤其是函数指针。


3
typedef一个struct的情况是存在的吗? - Panzercrisis
3
@Panzercrisis:我不知道有没有,当然在1989年至1998年(我大部分C语言工作的年份)期间,我经常这样做,但我不再是C语言专家了。 - T.J. Crowder
但通常,struct 的所有子类型都将是简单类型(如 shortdouble)的 typedef,有时这些类型是 typedeftypedef,这会让你在各种 .h 文件中进行兔子狩猎,最终你会忘记它的用途,并且你必须为每个变量都这样做。它们是一场噩梦! - CpILL

32

来自维基百科:

typedef是C和C++编程语言中的一个关键字。typedef的目的是为现有类型指定替代名称,最常见的是那些标准声明繁琐、可能令人困惑或可能因实现而异的类型。

另外:

K&R认为使用typedef有两个原因。首先,它提供了一种使程序更具可移植性的方法。不必在程序的所有源文件中都更改类型,只需更改单个typedef语句即可。其次,typedef可以使复杂的声明更易于理解。

还有反对的观点:

Greg K.H.认为这种做法不仅会使代码变得难以理解,还可能导致程序员错误地使用大型结构体,认为它们是简单的类型。


我完全同意Greg K.H.的观点,可以看看我在@T.J.Crowder下面的评论。我认为这是一种不好的做法,应该尽量少使用。 - CpILL

16

Typedef 用于创建对现有类型的别名。这有点称为误称:typedef 并不像它所表面的那样定义新的类型,因为新类型可以与基础类型互换使用。当基础类型可能会发生变化或者不重要时,typedef通常用于接口定义的清晰性和可移植性。

例如:

// Possibly useful in POSIX:
typedef int filedescriptor_t;

// Define a struct foo and then give it a typedef...
struct foo { int i; };
typedef struct foo foo_t;

// ...or just define everything in one go.
typedef struct bar { int i; } bar_t;

// Typedef is very, very useful with function pointers:
typedef int (*CompareFunction)(char const *, char const *);
CompareFunction c = strcmp;

typedef也可用于给无名类型命名。在这种情况下,typedef将是该类型的唯一名称:

typedef struct { int i; } data_t;
typedef enum { YES, NO, FILE_NOT_FOUND } return_code_t;

命名惯例不同。通常建议使用 trailing_underscore_and_tCamelCase


如此描述,不建议使用“_t”来命名自己的类型:https://dev59.com/zHVC5IYBdhLWcg3woSpW#231807 - Gregory Arenius

5

以下是typedef的使用示例解释。此外,typedef用于使代码更易读。

#include <stdio.h>
#include <math.h>

/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/

// typedef a primitive data type
typedef double distance;

// typedef struct 
typedef struct{
    int x;
    int y;
} point;

//typedef an array 
typedef point points[100]; 

points ps = {0}; // ps is an array of 100 point 

// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)

// prototype a function     
distance findDistance(point, point);

int main(int argc, char const *argv[])
{
    // delcare a function pointer 
    distanceFun_p func_p;

    // initialize the function pointer with a function address
    func_p = findDistance;

    // initialize two point variables 
    point p1 = {0,0} , p2 = {1,1};

    // call the function through the pointer
    distance d = func_p(p1,p2);

    printf("the distance is %f\n", d );

    return 0;
}

distance findDistance(point p1, point p2)
{
distance xdiff =  p1.x - p2.x;
distance ydiff =  p1.y - p2.y;

return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
} In front of everything, place the keyword typedef.
    */

当阅读代码时,像double这样的typedef标准类型只会让人感到困惑,它是一个结构体还是一个数组或者其他什么?你必须去寻找它的定义,并记住可能数百个新的标准类型名称,而所有这些名称都可以以相同的方式命名。最终,您需要知道底层类型才能正确使用变量。 - CpILL
@CpILL,虽然我同意你所说的,但我认为你错过了一个重要的点。想象一下,你正在编写一个网络堆栈,并且你想使用一个数据结构(在C中)来表示具有所有相关特征的节点。在这种情况下,将包含所有所需变量的结构体命名为“node”非常方便。请看我在这里的使用方式。 - Amjad
你把结构体隐藏在了一个 typedef 后面,这正是我的观点!当你声明一个变量时,它的类型应该是显而易见的,所以 struct RBuf buff;rbuf_t buff; 更容易理解,因为 rbuf_t 是什么鬼?人们必须去查找并记住它才能使用你的代码。 - CpILL

4

来自维基百科: “K&R指出,使用typedef有两个原因。首先...。其次,typedef可以使复杂的声明更易于理解。”

下面是一个使用typedef简化复杂类型的例子(复杂类型来自K&R的《C程序设计语言第二版》第136页)。

char (*(*x())[])()

x是一个返回指向函数指针数组[]的指针的函数。

我们可以使用typedef使上述声明更易懂。请参考下面的示例。

typedef char (*pfType)(); // pf is the type of pointer to function returning
                          // char
typedef pfType pArrType[2];  // pArr is the type of array of pointers to
                             // functions returning char

char charf()
{ return('b');
}

pArrType pArr={charf,charf};
pfType *FinalF()     // f is a function returning pointer to array of
                     // pointer to function returning char
{
return(pArr);
}

4

typedef并不引入新类型,它只是为一个类型提供了一个新的名称。

TYPEDEF可用于以下情况:

  1. 结合数组、结构体、指针或函数等类型。

  2. 为了方便移植,在需要的类型上使用typedef。然后当您将代码移植到不同的平台时,通过仅更改typedef来选择正确的类型。

  3. typedef可以为复杂的类型转换提供简单的名称。

  4. typedef也可用于为无名类型命名。在这种情况下,typedef将是该类型的唯一名称。

注意:不应该在结构体中使用typedef。即使不需要,也应该在结构体定义中使用标签。


6
请问您能否详细阐述一下为什么不建议在结构体中使用typedef呢? - Matvey Aksenov

2
它可以别名另一种类型。
typedef unsigned int uint; /* uint is now an alias for "unsigned int" */

OP询问为什么而不是如何。 - CpILL

2
typedef unsigned char BYTE;

在这个类型定义之后,标识符BYTE可以作为unsigned char类型的缩写使用,例如.. BYTE b1, b2;

2
OP询问为什么而不是如何。 - CpILL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接