typedef 关键字一些理解

巩固一下typedef关键字的用法...

用法

typedef是 C 语言的关键字之一,人尽皆知的用法就是“为一个类型取别名”,比如:

test1
1
2
typedef unsigned int size_t;
typedef char bool;

或者:

test2
1
2
3
4
5
typedef struct Student student;
typedef struct Teacher {
char name[NAMESIZE];
int age;
} teacher;

还有:

test3
1
2
3
4
5
typedef struct Node* PtrtoNode;
typedef struct Node {
PtrtoNode next;
int data;
} node;

类似的例子有很多,但实际上“为一个类型取别名”这种说法是不严谨的。私认为typedef关键字不仅仅是“取别名”,还要从语义的角度上去理解typedef的行为。
比如:

test4
1
2
3
typedef int Arr[5];
Arr *a;
int (*parr)[5];

从语义的角度而言,在上述代码中,Arr是一种“新类型”(这里的新类型其实并不是真正意义上新类型),表示元素个数为 5 的int数组,对应的a是一个指向元素个数为 5 的int数组的数组指针。对比类型一样、用基本类型声明的数组指针parr,也可以看出使用typedef带来的便利性。
实际上,熟悉 C++ 的同学,可能会发现typedefusing的功能有点类似。

类似的用法,还有定义函数指针的用法,如下:

test5
1
typedef void (*pfun)(int);

上述代码中,定义了一个返回值为void,参数为一个int的函数指针类型pfun

陷阱

这里,还需要提一下typedefconst关键字一起使用时的陷阱——千万不要把typedef#define的文本替换混为一谈
比如:

test5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

typedef char *pchar;

int main() {
char s1[10] = "hello";
char s2[10] = "world";
const pchar str = s1;
// str = s2; // error
*str = 'g';
puts(s1);

const char *pc = s1;
pc = s2;
// *pc = 'g'; // error
puts(pc);

int i = 0, j = 2;
const int *pi = &j;
pi = &i;
// *pi = 2; // error
int * const ppi = &i;
*ppi = 3; // correct
printf("%d\n", *pi);
return 0;
}
/*
out:
gello
world
3
*/

在阅读下面的讨论之前,需要理解const typename *typename * const的区别。

如果认为typedef是文本替换,那么const pchar strconst char *str一致,对应语句*str = 'g';就会出错,而str = s2;就会正常执行(可以对比下面const char *const int相关的代码)。但事实上,结果正好相反,编译器认为*str = 'g';正确、str = s2;错误,这说明,编译器并不认为str是一个const char *

从语义的角度来理解,pchar的类型是char型的指针,在其前面加上一个const,表示这个指针是一个常量,所以const pchar的实际类型是char * const,而不是const char *,这点从后面的代码也可以对比出来。

最后需要说明的是,typedef的用法是 C 的标准规定的,本文只是验证如何使用,而不是证明这是编译器的黑魔法😂。


Buy me a coffee ? :)
0%