C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,typedef 的真正含义是给一个已经存在的类型名称起一个别名,注意是已经存在的数据类型,而非变量
typedef 可以给下面的类型取别名,基本数据类型,数组类型名称,指针类型名称和用户自定义的结构体类型,枚举类型,共用类型
一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型来定义变量的类型,数组类型,指针变量类型和函数类型等,typedef 不是真正创造了一种数据类型,而是给已有的绘制复合型的以及复杂的数据类型取一个更加容易理解的别名。
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
上面是为已有的数据类型起了一个别名,使用 int8_t 的时候 就和使用 signed char 类型是一致的,此外,我们还可以使用这种方法来定义于平台无关的类型,这样,当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。
// pointer 一个指向 int 类型的指针类型
typedef int *pointer;
// 一个数组类型 pointerarray
typedef int *pointerarray[10];
// 数组指针类型arraypointer, 数组元素为 int 类型,数组大小为10
typedef int (*arraypointer)[10];
typedef int array[];
// 数组类型 fixedarray,数组元素为 int 类型,数组大小为10
typedef int fixedarray[10];
// 二维数组类型,数组元素为 int 类型,数组大小为10 *10
typedef int fixedsarray[10][10];
typedef int *pointer 定义了一个指针类型,当我们使用 pointer p 声明一个指针变量就和使用 int *p 的含义是一样的
typedef int *pointerarray[10] 定义了一个数组类型,当我们使用 pointerarray p 声明变量 p,表示声明一个数组 p ,数组大小为10,数组的元素类型为 int*
/*p[0] = 0053F968
p[1] = 0053F96C
p[2] = 0053F970
p[3] = 0053F974
p[4] = 0053F978
p[5] = 0053F97C
p[6] = 0053F980
p[7] = 0053F984
p[8] = 0053F988
p[9] = 0053F98C*/
{
int a[10] = {0};
pointerarray p = {NULL};
for (int i = 0; i < 10; i++) {
p[i] = &a[i];
}
for (int i = 0; i < 10; i++) {
printf("p[%d] = %p \n", i, p[i]);
}
printf("\n");
}
typedef int (*arraypointer)[10]; 定义了一个数组指针类型,当我们使用 arraypointer p 声明变量 p,表示声明一个指针变量 p,p 指向一个元素类型为 int,大小为 10 的数组
typedef int fixedarray[10];
typedef int fixedsarray[10][10];
定义了两个数组类型,fixedarray a,表示定义了一个元素类型为 int,大小为10 的数组,同理fixedsarray 表示的是 10x10 的二维数组
typedef struct {
int x;
int y;
int width;
int height;
} stBufferinfo;
typedef struct {
int x;
int y;
int width;
int height;
} *pstBufferinfo;
typedef enum {
MON,
TUE,
WED,
THR,
FRI,
SAT,
SUN,
} enweekday;
typedef enum {
sMON,
sTUE,
sWED,
sTHR,
sFRI,
sSAT,
sSUN,
} *penweekday;
stBufferinfo 定义了一个结构类型,stBufferinfo bufferinfo 就表示定义了一个结构体,结构体类型为stBufferinfo,结构体变量名为 bufferinfo。
pstBufferinfo 定义了一个指针类型,指向的是pstBufferinfo 前定义的结构体类型
同理 enweekday 和 penweekday 也是定义了了一个枚举类型和指向枚举的指针类型
typedef int stfunction(int a, int b);
typedef int (*pstfunction)(int a, int b);
typedef int *prstfunction(int a, int b);
stfunction 定义的是一个函数类型,此函数返回值为int,两个参数都是 int 类型,但是C语言中不存在函数的类型,使用时可以使用 stfunction* 的形式定义一个函数指针。
pstfunction 直接定义个函数指针类型
注意 prstfunction 和 pstfunction相比只是少了括号,含义却是一个函数类型,返回值为 int 类型指针,有两个int 类型的参数
{
stfunction *pfunc = CommonAdd;
//stfunction *pfunc = &CommonAdd;
printf("test pfunc a + b = %d \n", pfunc(10, 20));
printf("test pfunc a + b = %d \n", (*pfunc)(10, 20));
}
printf("=========================================\n");
{
pstfunction pfunc = CommonAdd;
printf("test pfunc a + b = %d \n", pfunc(10, 20));
printf("test pfunc a + b = %d \n", (*pfunc)(10, 20));
}
printf("=========================================\n");
{
//prstfunction = CommonAdd;
}
注意函数指针赋值时,可以直接使用函数名,也可以对函数名取地址。
typedef 的功能是为已经存在的类型起一个别名,这一点 #define 也可以做到,但是除此之外 #define 还有其他用处,这个是 typedef 所不具备的。
从执行时间上讲,对于 #define 定义的宏,在预处理阶段就会被替换,而 typedef 的定义是在编译期间处理
从一般来说 #define 定义的宏没有作用域的限制,只要在使用前定义就可以,而 typedef 定义的别名是有作用域的(在文件头声明或者在函数中声明有区别)
我们使用 typedef 定义一个指针类型,然后使用该类型可以同时声明多个变量,而 #define 却不是这样的。例如,typedef (int*) pType; 可以使用pType a, b; 这里 a 和 b 都是指向整数的指针变量。但我们同样定义 #define pType int*, 若使用 pType a, b; 定义 a 和 b,则 a 是指向整数的指针变量,而 b 不是。
从功能范围来讲,typedef 主要是为已经存在的关键字或者类型及其组合取一个我们容易识别的别名。在这一点上 #define 也可以实现,但除此之外 #define 还有其他用处,如果愿意的话你可以使用它定义任何代码,这是 typedef 所不具备的。
从执行时间来讲,对于 #define 定义的宏,其在预处理阶段就会被替换,而 typedef 定义的类型会在编译时处理。
从作用域上来讲,一般来说 #define 定义的宏没有作用域的限制,只要在使用前定义就可以,而 typedef 定义的别名是有作用域的。
从实现效果来讲,我们使用 typedef 定义一个指针类型,然后使用该类型可以同时声明多个变量,而 #define 却不是这样的。例如,typedef (int*) pType; 可以使用pType a, b; 这里 a 和 b 都是指向整数的指针变量。但我们同样定义 #define pType int*, 若使用 pType a, b; 定义 a 和 b,则 a 是指向整数的指针变量,而 b 不是。
还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:
typedef static int marray[];