C语言typedef与#define详谈

一、typedef#define比较

typedef#define功能的共同点

例如:

1
#define BYTE unsigned char

表示预处理器用BYTE替换unsigned char

1
typedef unsigned char BYTE

表示编译器给类型unsigned char起了一个别名BYTE

typedef#define的区别

#define只是替换,由预处理器执行,#define A B即意味着将B用A替换。

#define不同,typedef具有以下特点:

  • typedef给出的符号名称仅限于类型,而不是数值。
  • typedef的解释由编译器执行,不是简单的文本替换。
  • 虽然范围有限,但是在有限范围内typedef#define更灵活。

(1) 连续定义多个变量时typedef#define的区别。

1
typedef char * STRING

表示编译器把STRING解释为一个类型的标识符,该类型指向char

所以:

1
STRING name, sign;

相当于:

1
char * name, * sign;
1
#define STRING char *

表示预处理器将用STRING替换char *标识符。

1
STRING name, sign;

将被翻译成:

1
char *name, sign;

结果是name是一个指针,sign是一个字符类型。

(2) #define可以使用其他类型名对宏类型名进行拓展,但typedef定义的类型名不能用其他类型进行拓展。

1
2
3
4
5
6
7
#define INTERGE int;

unsigned INTERGE n; //正确

typedef int INTERGE;

unsigned INTERGE n; //错误,不能在INTERGE前面添加unsigned

二、typedef的主要用法

用法一:

1、为基本数据类型定义一个别名,不是简单的宏替换。可以用作同时声明多个指针对象。比如:

1
char * pa, pb;      // 这只是声明了一个指向字符的指针

换一种可行的方式:

1
2
3
typedef char * PCHAR;

PCHAR pa, pb;

实际上等同于:

1
char * pa, *pb;

2、为数组定义简洁名称。

示例代码为:

1
2
typedef int INT_ARRAY_100[100];
INT_ARRAY_100 arr;

用法二:

1、用在旧的C代码中,帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名对象名,如:

1
2
3
4
5
6
struct tagPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名对象名,即:

1
tagPOINT1 p1;
1
2
3
4
5
typedef struct tagPOINT
{
int x;
int y;
}POINT;
1
POINT p1; // 这样就比原来的方式少写了一个struct

2、另外,还可以为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称。

以结构体为例,下面我们定义一个名为Point的结构体:

1
2
3
4
5
6
struct Point
{
double x;
double y;
double z;
};

调用这个结构体:

1
2
struct Point oPoint1={100,10,0};
struct Ponit oPoint2;

在这里,结构体 struct Point 为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct,而不能像 intdouble 那样直接使用 Point 来定义变量。现在,我们利用 typedef 定义这个结构体,如下面的代码所示:

1
2
3
4
5
6
typedef struct tagPonit
{
double x;
double y;
double z;
}Point;

在上面的代码中,实际上完成了两个操作:

(1)定义了一个新的结构体类型,代码如下:

1
2
3
4
5
6
struct tagPoint
{
double x;
double y;
double z;
};

现在已经定义了一个新的结构体类型tagPoint

(2)使用typedef为这个新的结构体起一个别名,叫Point,即:

1
typedef struct tagPoint Point;

因此,现在你就可以像 int 和 double 那样直接使用 Point 定义变量,如下面的代码所示:

1
2
Point oPoint1={100,10,0};
Point oPoint2;

使用typedef规范定义结构体的方法:

1
2
3
4
5
6
struct tagNode
{
char *pItem;
struct tagNode *pNext;
};
typedef struct tagNode *pNode;

推荐使用这种使用typedef规范定义结构体的方法,在定义链表时经常会用到。

用法三:

用typedef来定义与平台无关的类型。

多使用在跨平台移植程序时!

比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:

1
typedef long double REAL;

在不支持 long double 的平台二上,改为:

1
typedef double REAL;

在连 double 都不支持的平台三上,改为:

1
typedef float REAL;

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。

标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。

参考文献:

关于typedef的用法总结

typedef的用法,C语言typedef详解

Author: wnxy
Link: https://wnxy.github.io/2021/03/17/C-typedef-and-define-specific-explain/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.