typedef总结
1、typedef 为类型起别名
typedef的第一个用途,就是起别名,一般是为复杂的声明定义一个新的简单的别名。
格式一:typedef+旧类型名字+新类型名字
格式二:直接使用新的类型名字替代原复杂定义中的类型名字
int(*funcp)(int a, int b);//定义一个函数指针
typedef int(*FP)(int a, int b);//定义一个函数指针类型
FP p1,p2,p3;//同时定义了多个函数指针
作用一是为了方便,为一个复杂的定义起一个简单的别名,使用起来也比较方便,不用每次都输入一串复杂的
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char s8;
typedef signed short int s16;
typedef signed int s32;
typedef signed long long int s64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
作用二是为了兼容:
typedef
有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫REAL
的浮点类型,在目标机器上它可以i获得最高的精度:
typedef long double REAL;
在不支持 long double
的机器上,该 typedef
看起来会是下面这样:
typedef double REAL;
并且,在连double
都不支持的机器上,该 typedef
看起来会是这样:
typedef float REAL;
你不用对源代码做任何修改,便可以在每一种平台上编译这个使用 REAL 类型的应用程序。唯一要改的是 typedef 本身。
2、typedef配合结构体使用
定义一个结构体
struct People{
int age = 18;
string name;
};
使用typedef
为一个结构体People
起一个别名P
typedef struct People{
int age = 16;
string name;
}P;
在C语言中,也支持省略原结构体名字的形式,但是这种方式在C++中似乎不太行,会报错。这也提醒我们,C代码就是C代码,C++代码就是C++代码,不要写一些C和C++混合的代码,否则到时候BUG够你受的。
typedef struct {
int age = 16;
string name;
}P;
3、typedef配合枚举类型使用
与结构体一样,我们也可以使用typedef
来为一个枚举类型起一个别名
typedef enum IRQn{
Software0_IRQn = 0,
Software1_IRQn = 1,
Software2_IRQn = 2,
Software3_IRQn = 3,
Software4_IRQn = 4,
Software5_IRQn = 5,
Software6_IRQn = 6,
Software7_IRQn = 7,
Software8_IRQn = 8,
Software9_IRQn = 9,
Software10_IRQn = 10,
}IRQn_Type;
总结
个人认为typedef
最重要的作用其实起别名,在有些时候别名的使用会使问题简单不少。
其实本来我来看关于typedef
的内容就是因为我在学习嵌入式时遇到这样一段代码,当时是有点晕的,现在清晰了不少,下面来分析分析。
/* 中断服务函数形式 */
typedef void (*system_irq_handler_t) (unsigned int giccIar, void *param);
代码第一行首先定义一个函数指针的类型,用于指向不同中断服务函数,一般用在形参当中,例如:
void system_register_irqhandler(IRQn_Type irq, system_irq_handler_t handler, void *userParam);
在函数system_register_irqhandler
的声明中:
参数irq
是一个IRQn_Type
类型的参数,那么这个IRQn_Type
又是什么类型呢,正是我们上面定义的枚举类型。
参数handler
是一个system_irq_handler_t
类型的形参,这个system_irq_handler_t
就是在开头定义的一个函数指针类型。而通过函数指针来调用函数是相当方便的,只需要把指针名字当成函数名字来用就行,是不是很方便。
参数*userParam
是一个空指针,用于接收用户参数,在需要的时候可以转换成任意类型的指针变量。
typedef与#define的区别
typedef与#define均可以用来起别名,但是在起别名这一方面,用一个不恰当的解释那就是typedef比#define多一个括号,为什么这么说呢,请看下面代码。
#define P1 int* //定义P1为int*的别名
void mian()
{
const P1 p1; //相当于 const int * p1 (p1为一个常量指针)
int a = 1;
p1 = &a;
}
我们都知道在使用#define的时候,计算机是在预处理阶段,将代码中所有的P1
替换为int *
因此在这里我们就是相当于创建了一个常量指针。
typedef int* P2; //使用typedef为int*起别名P2
void main()
{
int b = 2;
const P2 p2=&b; //定义了一个指针常量并初始化
cout << *p2 << endl;
}
这里的代码const P2 p2;
与前面#define
部分形式完全一样,但是这个地方定义的p2指针却是一个指针常量,这就是typedef与#define之间的区别,#define仅仅是在程序预编译的阶段进行了简单的替换工作,而typedef是在编译阶段起作用的,作用是将int*
捆绑成一个整体,定义为P2,所以在使用代码const P2 p2;
的时候const关键字修饰的是后面紧跟的东西,而这个地方后面紧跟着的是一个整体,所以const修饰的就是指针,指针不可修改,因此这是一个指针常量,指针常量在定义的时候需要进行初始化。
所以你现在应该就会理解我为什么说typedef比#define多一个括号,因为typedef将要起别名的原始代码捆绑成了一个整体,加了一个“括号”。
typedef可以同时定义多个指针,而#define稍麻烦一点
#define P1 int*
typedef int* P2;
void main()
{
P1 a, b, c;
P2 d, e, f;
cout << a << b << c << e << d << f << endl;
}
在上面的代码中,a是一个指针,而b和c只是一个int类型的变量;d,e,f均是int*
类型的指针变量。
想要用P1来定义多个指针,需要如下操作:
P1 a, *b, *c; //定义三个指针
这里只需要将P1替换为int*
就明白了,这里不再解释了。