1、执行上不同

关键字 typedef 在编译阶段有效,由于是在编译阶段,因此 typedef 有类型检查的功能。

#define 则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查。

例如:typedef 会做相应的类型检查

typedef unsigned int UINT;

void func()
{
UINT value = "abc"; // error C2440: 'initializing' : cannot convert from 'const char [4]' to 'UINT',会编译不通过
cout << value << endl;
}

#define不做类型检查:

// #define用法例子:
#define f(x) x*x
int main()
{
int a=6, b=2, c;
c=f(a) / f(b);
printf("%d\n", c);
return 0;
}

程序的输出结果是: 36,根本原因就在于 #define 只是简单的字符串替换。

2、功能有差异

typedef 用来定义类型的别名,定义与平台无关的数据类型,与 struct 的结合使用等。

比如:定义一个叫 FALSE 的浮点类型,在目标平台一上,让它表示最高精度的类型为:

typedef long double FALSE;

在不支持 long double 的平台二上,改为:

typedef double FALSE;

在连 double 都不支持的平台三上,改为:

typedef float FALSE;

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。

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

3、作用域不同

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

而 typedef 有自己的作用域。

例如:没有作用域的限制,只要是之前预定义过就可以

void func1()
{
#define HW "HelloWorld";
} void func2()
{
string str = HW;
cout << str << endl;
}

而typedef有自己的作用域:

函数:

void func1()
{
typedef unsigned int UINT;
} void func2()
{
UINT uValue = 5;//error C2065: 'UINT' : undeclared identifier,在此函数中未定义
}

类:

class A
{
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
}; class B
{
UINT valueB;
//error C2146: syntax error : missing ';' before identifier 'valueB'
//error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
};

上面例子在B类中使用UINT会出错,因为UINT只在类A的作用域中。

此外,在类中用typedef定义的类型别名还具有相应的访问权限:

class A
{
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
}; void func3()
{
A::UINT i = 1;
// error C2248: 'A::UINT' : cannot access private typedef declared in class 'A'
}

默认的typedef为私有,而给UINT加上public访问权限后,则可编译通过。

class A
{
public:
typedef unsigned int UINT;
UINT valueA;
A() : valueA(0){}
}; void func3()
{
A::UINT i = 1;
cout << i << endl;
}

4、对指针的操作

二者修饰指针类型时,作用不同。

typedef int * pint;
#define PINT int * int i1 = 1, i2 = 2; const pint p1 = &i1; //p不可更改,p指向的内容可以更改,相当于 int * const p;
const PINT p2 = &i2; //p可以更改,p指向的内容不能更改,相当于 const int *p;或 int const *p; pint s1, s2; //s1和s2都是int型指针
PINT s3, s4; //相当于int * s3,s4;只有一个是指针。 void TestPointer()
{
cout << "p1:" << p1 << " *p1:" << *p1 << endl;
//p1 = &i2; //error C3892: 'p1' : you cannot assign to a variable that is const
*p1 = 5;
cout << "p1:" << p1 << " *p1:" << *p1 << endl; cout << "p2:" << p2 << " *p2:" << *p2 << endl;
//*p2 = 10; //error C3892: 'p2' : you cannot assign to a variable that is const
p2 = &i1;
cout << "p2:" << p2 << " *p2:" << *p2 << endl;
}

结果:

p1:00EFD094  *p1:1
p1:00EFD094 *p1:5
p2:00EFD098 *p2:2
p2:00EFD094 *p2:5

转载

1、C++ 数据类型

C++:typedef 与 #define 的区别的更多相关文章

  1. typedef 和 #define 的区别

    本文已迁移至: http://www.danfengcao.info/c/c++/2014/02/25/difference-between-define-and-typedef.html typed ...

  2. typedef与#define的区别

    1.  typedef typedef故名思意就是类型定义的意思,但是它并不是定义一个新的类型而是给已有的类型起一个别名,在这一点上与引用的含义类似,引用是变量或对象的别名,而typedef定义的是类 ...

  3. typedef 和define的区别

    总结一下typedef和#define的区别 1.概念 #define 它在编译预处理时进行简单的替换,不作正确性检查.它是预处理指令. typedef 它在自己的作用域内给一个已经存在的类型一个别名 ...

  4. typedef 与define 的区别

    typedef和#define的用法与区别   typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译 ...

  5. typedef和#define的区别

    转自:http://www.cnblogs.com/kerwinshaw/archive/2009/02/02/1382428.html 一.typedef的用法在C/C++语言中,typedef常用 ...

  6. typedef 与 #define的区别

    typedef 与 #define的区别 整理于一篇经典blog,经典原文地址http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.ht ...

  7. C++中typedef和define的区别

    typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像: ...

  8. C++ 系列:typedef 和 #define 的区别

    总结一下typedef和#define的区别 1.概念 #define 它在编译预处理时进行简单的替换,不作正确性检查.它是预处理指令. typedef 它在自己的作用域内给一个已经存在的类型一个别名 ...

  9. typedef 与 define 的区别

    1.区别 (1)定义.执行时间.作用域 定义.执行时间: #define pchar char * typedef char *pchar; 定义的格式差别,显而易见的,要注意,define 是不能存 ...

  10. C语言中的typedef跟define的区别

    今天用C语言练习时涉及到了typedef和define的使用问题,那么他们的区别是啥?这种情况下为什么要用typedef?哪种情况下为什么要用define呢? 学习C的时候的你是否考虑过这个问题呢? ...

随机推荐

  1. C#中的9个“黑魔法”

    C#中的9个"黑魔法"与"骚操作" 我们知道C#是非常先进的语言,因为是它很有远见的"语法糖".这些"语法糖"有时过于好 ...

  2. ThreeJs-01开发环境搭建

    写在前面,好久不见各位,之前一段时间因为一些事情有点忙,但从未停止学习的脚步,也屯了很多笔记,会在未来的时间慢慢发出来,从今天开始一起进入WebGis,threeJs目前大前端发展的一个方向开始学习, ...

  3. Quartz集群增强版_02.任务轮询及优化❤️

    Quartz集群增强版_02.任务轮询及优化 转载请著名出处 https://www.cnblogs.com/funnyzpc/p/18555665 开源地址 https://github.com/f ...

  4. Ansible常用功能说明 [异步、并发、委托等]

    文章目录 Ansible的同步模式与异步模式 Ansible的异步和轮询 [async.poll] Ansible的并发限制 [serial.max_fail_percentage] Ansible的 ...

  5. Mybatis【6】-- Mybatis插入数据后自增id怎么获取?

    代码直接放在Github仓库[https://github.com/Damaer/Mybatis-Learning/tree/master/mybatis-05-CURD ] 需要声明的是:此Myba ...

  6. whisper v3 finetune 中文乱码问题的解决方案

    最近学习了一下whisper的微调,主要是参考了github上的夜雨飘零大神项目.但是在操作中遇到了微调中文的时候出现了乱码的情况.以下是我这边对于微调过程中中文出现乱码情况的解决方案. 出现情况如下 ...

  7. Zoom

    1.zoom to layer ILayer layer = (ILayer)m_mapControl.CustomProperty; m_mapControl.Extent = layer.Area ...

  8. redis设置密码和开启远程访问

    改密码 默认redis安装后,密码是默认的,通过查看安装目录的config文件,可以查到:requirepass 这个设置,默认是啥就是啥. 需要修改密码的话,把这个注释拿掉,将requirepass ...

  9. cas5配置LDAP的域控验证

    ​pom.xml 在这个下面添加LDAP依赖: <!-- ...Additional dependencies may be placed here... --> <dependen ...

  10. 再次探讨 WinForms 多线程开发

    再次探讨 WinForms 多线程开发 WinForms 已经开源,您现在可以在 GitHub 上查看 WinForm 源代码. 正好有人又讨论到在 WinFroms 环境下的多线程开发,这里就再整理 ...