#define和typedef 区别与用法

一、前言

虽然都是为一种类型创建自定义的名字,但之间还是有很打的差别的。
使用形式:
#define my_int int

typedef int my_int

二、typedef的用途

1. 用途一:

用作同时声明指针类型的多个对象,比如:

int *pa,pb;

//相当于
int *pa;
int pb;

这里相当于只定义了一个指向int型变量的指针pa,而pbint整型变量,不是指针。

但是typedef可以实现定义多个指针类型变量

typedef	(int*) P_INT;
P_INT pa,pb;

虽然使用int *pa, *pb;也可以完成上面操作,但是没有typedef 直观简单,尤其在大量需要指针的地方。

2. 用途二:

在以前代码中,声明 struct 新对象时:struct 结构名 对象名

struct RecTangle
{
    
    
	int length;
	int width; 
};
// 声明一个新对象Rec1
struct RecTangle Rec1;

使用typedef 则可以比原来少写struct,在大量使用时比较省时省力。
(需要注意在C++中可以直接结构名 对象名,即:RecTangle Rec1;

typedef	struct RecTangle
{
    
    
	int length;
	int width; 
} RecT;

// 声明一个新对象Rec1
RecT Rec1;
3. 用途三:

用typedef来定义与平台无关的类型。

  • 比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:
    typedef long double	REAL
    
  • 在不支持 long double 的平台二上,改为:
    typedef double	REAL
    
  • 在连 double 都不支持的平台三上,改为:
    typedef	float REAL
    

当代码跨平台时,只需要修改typedef就可以,不用去改其他源码,比如经常使用的uint_32_t:

4. 用途四:

给指向函数的指针类型起别名

#include <stdio.h>
//给指向函数的指针,起了个别名叫MySum
//被指向的函数接收2个int类型的参数,返回值为int类型
typedef int (*MySum)(int ,int);

// 定义一个sum函数,计算a,b的和
int sum(int a, int b)
{
    
    
	int sum = a + b;
	return sum;
}

int main()
{
    
    
	// 定义一个指向sum函数的指针变量p
	MySum p = sum;
	
	// 利用指针变量p调用sum函数
	printf("MySum Result: %d\n",p(4,5));
	
	return 0;
}
5. 用途五:

为复杂的声明定义一个新的简单的别名。
方法是:在原来的声明里逐步用别名替换一部分复杂的声明,如此循环,把带变量名的部分留在最后替换,得到的就是原声明的最简化版。eg:

// 原声明
void (*b[10]) (void (*)());
// 先替换右边括号里的(void (*)()) ,pFunParam为别名1
// 给指向函数的指针类型,起了个别名叫pFunParam
typedef void (*pFunParam)();
// 再替换左边的变量,pFunx为别名2
typedef void (*pFunx)(pFunParam);
//原声明的最简化:
pFunx b[10];

** 还在理解中,上面代码怎么去做应用和实现 **

理解复杂声明可用“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;
括号内分析完就调出括号,还是按先右后左的顺序循环,直到整个声明分析完,例:

int (*fun)(int *);
//首先找到变量名fun,外面有一对圆括号,左边有*号,说明fun是一个指针
//然后看右边圆括号,这说明(*fun)是一个函数,所以fun是一个指向这类函数的指针,即函数指针
//这类函数具有int*类型的形参,返回值类型为int
int (*fun[5])(int *);
//fun右边是[]运算符,说明fun具有5个元素的数组
//fun左边有*,说明fun的元素是指针(这里的*不是修饰fun,而是修饰fun[5]数组的内容)
//看右边括号,说明fun数组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int

三、区别

  1. #define 在“预处理过程”进行宏的替换与展开,不进行正确性的检查,无脑替换,不管正确与否都带入替换,安全性差,在编译阶段可能才会发现错误报错。
    #define		Add(a,b)	(a+b)
    
    // 正确
    Add(5+4)
    // 错误
    Add(x+4)	
    
  2. typedef 在“编译过程”,用来给标识符或者关键字起一个别名
  3. 建议能使用 typedef 就不使用 #define
  4. #define行末没有分号

猜你喜欢

转载自blog.csdn.net/qq_30722795/article/details/108117672