【C++】typedef和#define的用法与区别

typedef和define都是替一个对象取一个别名,以此增强程序的可读性,区别如下:

(1)原理不同

#define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。

typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。

(2)功能不同

typedef用来定义类型的别名,起到类型易于记忆的功能。另一个功能是定义机器无关的类型。如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL, 在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的,typedef float REAL

#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

(3)作用域不同

#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。

(4)对指针的操作不同

#define INTPTR1 int*

typedef int* INTPTR2;

INTPTR1 p1, p2;

INTPTR2 p3, p4;

含义分别为,

声明一个指针变量p1和一个整型变量p2

声明两个指针变量p3、p4

#define INTPTR1 int*

typedef int* INTPTR2;

int a = 1;

int b = 2;

int c = 3;

const INTPTR1 p1 = &a;

const INTPTR2 p2 = &b;

INTPTR2 const p3 = &c;

上述代码中,

const INTPTR1 p1是一个常量指针,即不可以通过p1去修改p1指向的内容,但是p1可以指向其他内容。

const INTPTR2 p2是一个指针常量,不可使p2再指向其他内容。因为INTPTR2表示一个指针类型,因此用const限定,表示封锁了这个指针类型。(这是使用typedef需要特别注意的地方)

INTPTR2 const p3是一个指针常量。


define還是很好理解的,但是typedef就比較難理解了,接下来再深入了解一下typedef的用法

函数指针的用法

使用自带的int类型举例

//#include<iostream.h>
#include<stdio.h>

typedef int (*FP_CALC)(int, int);
//注意这里不是函数声明而是函数定义,它是一个地址,你可以直接输出add看看
int add(int a, int b)
{
     return a + b;
}
int sub(int a, int b)
{
     return a - b;
}
int mul(int a, int b)
{
     return a * b;
}
int div(int a, int b)
{
     return b? a/b : -1;
}
//定义一个函数,参数为op,返回一个指针。该指针类型为 拥有两个int参数、
//返回类型为int 的函数指针。它的作用是根据操作符返回相应函数的地址
FP_CALC calc_func(char op)
{
     switch (op)
     {
     case '+': return add;//返回函数的地址
     case '-': return sub;
     case '*': return mul;
     case '/': return div;
     default:
         return NULL;
     }
     return NULL;
}
//s_calc_func为函数,它的参数是 op,
//返回值为一个拥有 两个int参数、返回类型为int 的函数指针
int (*s_calc_func(char op)) (int, int)
{
     return calc_func(op);
} 
//最终用户直接调用的函数,该函数接收两个int整数,和一个算术运算符,返回两数的运算结果
int calc(int a, int b, char op)
{
     FP_CALC fp = calc_func(op); //根据预算符得到各种运算的函数的地址
         int (*s_fp)(int, int) = s_calc_func(op);//用于测试
// ASSERT(fp == s_fp);   // 可以断言这俩是相等的
     if (fp) return fp(a, b);//根据上一步得到的函数的地址调用相应函数,并返回结果
     else return -1;
}

void main()
{   
    int a = 100, b = 20;

     printf("calc(%d, %d, %c) = %d\n", a, b, '+', calc(a, b, '+'));
     printf("calc(%d, %d, %c) = %d\n", a, b, '-', calc(a, b, '-'));
     printf("calc(%d, %d, %c) = %d\n", a, b, '*', calc(a, b, '*'));
     printf("calc(%d, %d, %c) = %d\n", a, b, '/', calc(a, b, '/'));
}

使用自己申明的类型举例

// initial_test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

template <typename T>
class Test
{
public:
	Test(T a)
	{
		cout << a << endl;
	}
	void show(char* a)
	{
		cout << a << endl;
	}
};

typedef Test<int>(*Mytest) (int);
Test<int> TestFunc(int a)
{
	Test<int>* C = new Test<int>(a);
	return *C;
}

typedef Test<int>(MytestY) (int);
Test<int> TestFuncY(int a)
{
	Test<int>* C = new Test<int>(a);
	return *C;
}

typedef Test<int>*(*MyTestX) (int);
Test<int>* TestFuncX(int a)
{
	Test<int>* C = new Test<int>(a);
	return C;
}

typedef int int_p;
typedef int(*int_o);
typedef int *int_i;


int _tmain(int argc, _TCHAR* argv[])
{
	Mytest test_int = TestFunc;
	test_int(1).show("Hello");

	/*MytestY test_int_Y = TestFuncY;  //会报错,不可以被赋值
	test_int_Y(1).show("Hello");*/   

	MyTestX test_int_2 = TestFuncX;
	test_int_2(2)->show("Hello2");

	int_p p(10); //调用的是构造函数

	MytestY test_func_y;
	Test<int> Y = test_func_y(3);
	Y.show("Hello3");

	int test_int_o_1 =21;
	int_o test_int_o = &test_int_o_1;
	int_i test_int_i = &test_int_o_1;

	return 0;
}

下面有两点需要总结:

第一点:

我们可以看到typedef Test<int>(*Mytest) (int);(与typedef Test<int>*(Mytest) (int);是不一样的,typedef Test<int>*(Mytest) (int);这种方式不是一个函数指针)和typedef Test<int>(MytestY) (int);就在于起别名的时候少加了一个*,可以发现前面的可以被赋值,后面的就不能被赋值。

我猜测跟指针有关系,也就是函数名其实本身就是一个指针,所以就可以直接赋值到相同的类型上。后面的不能赋值,因为typedef Test<int>(MytestY) (int);以及typedef Test<int>*(Mytest) (int);本身申明的就不是一个函数指针,所以就不能将一个指针赋值给他们所申明的对象。

第二点:

typedef int(*int_o);
typedef int *int_i;

这两种声明的方式是一样的,这个有没有括号都一样。因为声明的是指向整形的指针,不是指向函数的指针。

参考

https://blog.csdn.net/summer00072/article/details/80918483

https://blog.csdn.net/hai008007/article/details/80651886

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值