聊聊typedef
typedef
历史的误会-typedef也许应该是typerename
,typedef就是用来给类型重命名的
typedef功能
- typedef可以一次指定多个别名
typedef int A,B,C;
- typedef 为函数起别名的写法如下
typedef signed char (*fp)(void);
- typedef 也可以用来为数组类型起别名
typedef int five_ints[5];
five_ints x = {11, 22, 33, 44, 55};
简化类型声明
C 语言有些类型声明相当复杂,比如下面这个char (*(*x(void))[5])(void);
函数指针 :
typedef 返回值类型 ()(参数);
数组指针 :
typedef 返回值类型 ()[];
右左法则说明:右左法则不是标准C里面的内容,它是从C标准的声明规定中归纳出来的语法.C标准的声明规则是用来解决如何创建声明.而右左法则是用来解决如何辨识一个声明
右左法则内容:首先从最里面的标识符看起,然后往右看,再往左看.每当遇到圆括号时,就掉转阅读方向.一旦解析完 圆括号内的所有内容,就跳出圆括号.重复这个过程直到整个声明解析完毕.
根据右左法则, x的右边是(void),说明x是函数.x的左边是*,说明x的返回值类型是指针.
下一层括号的右边是[5],说明是元素个数为5的数组指针,左边是*,说明元素类型是指针.
下一层括号的右边是(void),说明是函数,左边是char,说明返回值类型是char,即数组元素为char (*)void
所以它是一个函数名为x,参数列表为void, 返回值为 大小为5,类型为char (*)void的数组指针 的函数指针.
typedef 可以简化复杂的类型声明,使其更容易理解。首先,最外面一层起一个类型别名。
typedef char (*Func)(void);
Func (*x(void))[5];
这个看起来还是有点复杂,就为里面一层也定义一个别名。
typedef char (*Func)(void);
typedef Func Arr[5];
Arr* x(void);
上面代码就比较容易解读了。
- x是一个函数,返回一个指向 Arr 类型的指针。
- Arr是一个数组,有5个成员,每个成员是Func类型。
- Func是一个函数指针,指向一个无参数、返回字符值的函数。
typedef与宏的区别
//区别1:
#define pINT int*
typedef int* PINT
PINT p1,p2;
pINT p3,p4;
p2是什么类型,p4是什么类型?
答:p2是整型指针,p4是整型. 可以看出typedef和宏有一定差别,用typedef更容易理解,更安全
typedef后的类型应理解为定义了一种全新的类型,而不是像宏一样直接替换.
typedef的用法注意
- typedef重命名后的类型,要注意正确使用修饰关键字
1.typedef后使用unsigned或signed可能会报错
typedef int INT;
int main() {
unsigned INT b; //error
}
2.const
3.static
不要过度使用typedef
使用typedef本质上就是封装,在某些情况下,封装隐藏内部细节会给代码阅读带来成本.
为什么typedef属于存储类型关键字
typedef 的作用并不直接涉及存储管理或者变量的具体存储方式,而是用于给现有类型创建一个新的名称,即类型别名。
尽管如此,将 typedef 归类为存储类型关键字可能是因为在概念上它确实影响了类型在程序中的“存储”方式——存储在类型系统中而不是实际内存布局中。通过 typedef,程序员可以在不改变类型本质的情况下更改类型的名称,从而在类型层次上“存储”新的类型定义。这样做的目的更多是为了提高代码的可读性和可维护性,尤其是在处理复杂类型(如指针、数组、函数指针或结构体)时,赋予它们更具描述性的名称。
实际上,typedef 主要用于类型定义,而不直接影响变量的存储类别或持续性。它主要在编译阶段起作用,帮助编译器理解和解析类型,并不影响运行时的行为。