C++--问题21--#define和typedef定义变量
typedef和define都是替一个对象取一个别名。
不同处:
1.原理不同
(1)#define,是预处理指令,在预处理时进行简单文本替换,不做正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。
(2)typedef,是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会很方便,不仅使程序书写简单,也使意义明确,增强可读性。
2.#define和typedef定义变量不同
#include <iostream>
using namespace std;
#define p char*
typedef char* pp;
int main()
{
p p1, p2;
pp pp1, pp2;
p1 = "string1";
p2 = 'c';
pp1 = "string2";
pp2 = "string3";
cout << p1 << " " << p2 << " " << pp1 << " " <<pp2 << " " << endl;
}
含义分别为:声明一个指针变量p1(char*)和一个字符变量p2(char)
声明两个指针变量pp1(char*)、pp2(char*)
其主要原因是原理不同,可看1。为了证明结果,分别给赋值并打印。
3.功能不同
typedef是用来定义类型的别名,起到类型易于记忆的功能。另一个功能是定义机器无关的类型。
如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:
typedef long double REAL;
在不支持long double的机器上,是这样的,typedef double REAL;
在不支持double的机器上,是这样的,typedef float REAL。
#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。
4.作用域不同
#define没有作用域的限制,而typedef有自己的作用域。
5.#define的## 和# 以及@#的用法
#include <iostream>
#include <string>
using namespace std;
#define CONNECT(a,b) a##b //连接ab
#define TOCHAR(a) #@a //转换为字符
#define TOSTRING(a) #a //转换为字符串
int main()
{
int a_b1 = CONNECT(123,456);
char* a_b2 = CONNECT("abc", "def");
char itoa1 = TOCHAR(1);
char itoa2 = TOCHAR(123); //只能输出3
char* str1 = TOSTRING(123);
cout << a_b1 << endl;
cout << a_b2 << endl;
cout << itoa1 << endl;
cout << itoa2 << endl;
cout << str1 << endl;
return 0;
}
上面代码输出的结果如下:
其中itoa2出错了,因为只能将一个数字转换为字符。比如itoa1 = 'a'.
6.#define不经宏定义,还可以定义函数
#include <iostream>
using namespace std;
#define Max(a,b) (a>b ? a : b)
#define Min(a,b) (a<b ? a : b)
//如果要换行要结尾添加反斜杠\。
#define Swap(a,b) do{\
int t = 0;\
t = a;\
a = b;\
b = t;\
}while(0)
int main()
{
cout << Max(3, 5) << endl;
cout << Min(3, 5) << endl;
int a = 3;
int b = 5;
Swap(a, b);
cout << a <<" " << b << endl;
return 0;
}
运行结果如下:需要注意的是#define 如果要换行末尾加反斜杠。
7.使用#undef可以撤销宏定义,#ifndef 的用法
#ifndef Max(a,b)
#define Max(a,b) (a>b ? a : b)
#undef Max(a,b)
#endif