C/C++语言typedef的用法详解以及与define的区别

x33g5p2x  于2022-03-18 转载在 其他  
字(2.8k)|赞(0)|评价(0)|浏览(445)

一、typedef用法详解

typedef 为C语言的关键字,作用是为一种数据类型定义一个新名字,这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

typedef 本身是一种存储类的关键字,与 auto、extern、static、register 等关键字不能出现在同一个表达式中。

C语言允许为一个数据类型起一个新的别名,就像给人起“绰号”一样。

起别名的目的不是为了提高程序运行效率,而是为了编码方便。例如有一个结构体的名字是 stu,要想定义一个结构体变量就得这样写:
struct stu stu1;

struct 看起来就是多余的,但不写又会报错。如果为 struct stu 起了一个别名 STU,书写起来就简单了:

typedef struct stu STU;
STU stu1;

这种写法更加简练,意义也非常明确,不管是在标准头文件中还是以后的编程实践中,都会大量使用这种别名。

使用关键字 typedef 可以为类型起一个新的别名。typedef 的用法一般为:

typedef int INTEGER;
INTEGER a, b;
a = 1;
b = 2;

INTEGER a, b;等效于int a, b。

typedef 还可以给数组、指针、结构体等类型定义别名。先来看一个给数组类型定义别名的例子:

typedef char ARRAY20[20];

表示 ARRAY20 是类型char [20]的别名。它是一个长度为 20 的数组类型。接着可以用 ARRAY20 定义数组:

ARRAY20 a1, a2, s1, s2;

它等价于:

char a1[20], a2[20], s1[20], s2[20];

注意,数组也是有类型的。例如char a1[20];定义了一个数组 a1,它的类型就是 char [20]。

又如,为结构体类型定义别名:

typedef struct stu{
    char name[20];
    int age;
    char sex;
} STU;

STU 是 struct stu 的别名,可以用 STU 定义结构体变量:

STU body1,body2;

它等价于:

struct stu body1, body2;

再如,为指针类型定义别名:

typedef int (*PTR_TO_ARR)[4];

表示 PTR_TO_ARR 是类型int * [4]的别名,它是一个二维数组指针类型。接着可以使用 PTR_TO_ARR 定义二维数组指针:

PTR_TO_ARR p1, p2;

按照类似的写法,还可以为函数指针类型定义别名:

typedef int (*PTR_TO_FUNC)(int, int);
PTR_TO_FUNC pfunc;

示例 为指针定义别名。

#include <stdio.h>

typedef char (*PTR_TO_ARR)[30];
typedef int (*PTR_TO_FUNC)(int, int);

int max(int a, int b){
    return a>b ? a : b;
}

char str[3][30] = {
    "http://www.baidu.com",
    "百度搜索引擎",
    "C-Language"
};

int main(){
    PTR_TO_ARR parr = str;
    PTR_TO_FUNC pfunc = max;
    int i;
   
    printf("max: %d\n", (*pfunc)(10, 20));
    for(i=0; i<3; i++){
        printf("str[%d]: %s\n", i, *(parr+i));
    }

    return 0;
}

运行结果:

max: 20
str[0]: http://www.baidu.com
str[1]: 百度搜索引擎
str[2]: C-Language

注意,typedef 是赋予现有类型一个新的名字,而不是创建新的类型。为了“见名知意”,请尽量使用含义明确的标识符,并且尽量大写。

二、typedef 和 #define 的区别

**typedef 在表现上有时候类似于 #define,但它和宏替换之间存在一个关键性的区别。**正确思考这个问题的方法就是把 typedef 看成一种彻底的“封装”类型,声明之后不能再往里面增加别的东西。

1 . 可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做。如下所示:

#define INTERGE int
unsigned INTERGE n;  //没问题

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

2 . 在连续定义几个变量的时候,typedef 能够保证定义的所有变量均为同一类型,而 #define 则无法保证。例如:

#define PTR_INT int *
PTR_INT p1, p2;

经过宏替换以后,第二行变为:

int *p1, p2;

这使得 p1、p2 成为不同的类型:p1 是指向 int 类型的指针,p2 是 int 类型。

相反,在下面的代码中:

typedef int * PTR_INT
PTR_INT p1, p2;

p1、p2 类型相同,它们都是指向 int 类型的指针。

  • typedef和define都是替一个对象取一个别名。

  • #define成了预编译指令,typedef当成语句处理。Typedef和define都可以用来给对象取一个别名,但是两者却有着很大不同。

  • #define和typedef原理不同

  • #define,是预处理指令,在预处理时进行简单文本替换,不做正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。

  • typedef,是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会很方便,不仅使程序书写简单,也使意义明确,增强可读性。

  • #define和typedef二者执行时间不同

  • 关键字typedef在编译阶段有效,由于是在编译阶段,因此typedef有类型检查的功能。

  • #define则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查。

  • #define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用。而typedef有自己的作用域。

  • #define和typede二者修饰指针类型时,作用不同

Typedef int* print;
#define PRINT int*
 
Const pint p;//p不可更改,p指向的内容可以更改,空间不能改,相当于 int * const p;
Const PRINT p;//p可以更改,p指向的内容不能更改,空间可以更改,相当于 const int *p;或 int const *p;

print s1, s2; //s1和s2都是int型指针
PRINT s3, s4; //相当于int* s3,s4;只有一个是指针,s3是指针,s4不是。

相关文章