typedef 与 #define的区别

整理于一篇经典blog,经典原文地址http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html

案例一:

通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:

typedef char *pStr1;

#define pStr2 char *;

pStr1 s1, s2;

pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。

案例二:

下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

typedef char * pStr;

char string[4] = "abc";

const char *p1 = string;

const pStr p2 = string;

p1++;

p2++;

============解释1:

是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和const long x本质上没有区别,都是对变量进行读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。

读不懂上面这段话是么,
其实也可以多读几次嘛。。
const pStr p2和const long x本质上没有区别,都是对变量进行只读限制。x是一个常量。它初始话之后是不可以改变的。
const pStr p2的含义是:限定数据类型为char *的变量p2为只读。
就可以理解为p2是一个常量。p2自身是不可以改变的。但它的类型是pStr是一个char *,说明它指向的数据是char,不是const char。说明p2指向的数据是可改的。。

============解释2:
const char *p1 = string; 你可以这样理解:(const char) *p1 = string, p1是一个指针,指向const char的东西,这个东西就是string(string是一个字符数组的首地址,它的地址声明后肯定是const的,除非该数组销毁),但是p1是一个指针变量,它是可以递增的,即你看到的p1++,它可以完成从数组的来遍历数组的目的。

而const pStr p2 = string;是这样的:由于p2不是指针,const直接修饰到了p2,即现在的p2是常量了,它的类型是pStr(我们自己定义的类型),相当于const int p2, const long p2等等,const都是直接修饰p2的,只不过int,long是系统类型,而pStr是我们定义的类型。为什么会出现这种效果了,就是因为typedef,它把char *定义成一个复合的类型,要从整体上来理解语义,而不是字符替换后来理解语义。

============解释3:
onst char *p1 = string 意思是说一个指向const char类型的指针。。
p1指针是一个变量。他可以指向任意的char对象。就算不是const定义的char也可以,p1可以指向不同的char对象,因为他是一个变量。但他无论是指向const char对象还是char对象。都不能改变其指向对象的值。就是说上例子p1不能对string做修改。只能读取string的值。

typedef char *pStr
const pStr p2 = string 这里是typedef和指针共用时的坑爹指出。
const pStr p2 = string
pStr const p2 = string
char* const p2 = string 上面3个语句是一个意思。
就是说p2是一个指向非const、char类型的对象的const指针。p2初始化之后就不能够指向第二个对象。但p2可以对string的值进行修改。。

看到这里你可能会觉得这不是说p2++正确么~那么请继续看解释~

p2++是错的。。p2本来就是一个指针。。而且是一个const。。就是说是一个常量指针。。你觉得一个const常量初始化之后还可以++吗。。。上面的解释是错的。。不知道是看什么书的。。你可以弄个程序看看。。我贴一下我刚才test的代码。。

#include<stdio.h>

int main(){
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2[2] = 'e';
printf(p1);
printf(p2);return 0;
}
p2指针可以对string进行修改。。可以p2不能动。。他是一个const常量!!!!!!!!!!!!!!!

但是p1可以移动。。但是p1却不能修改。。p2可以改。。可是不能移动。。我不懂怎么把指针的++操作说成了对char数组的操作了。。。
下面是代码。。我是用VS2010测试的。。不知道其他的编译器怎么样。。
#include<stdio.h>

int main(){
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1[1] = 'f';
p1++;
p2[2] = 'e';
p2++;
printf(p1);
printf(p2);
return 0;
}
下面是错误:
1>c:\test\typedef.cpp(8): error C3892: “p1”: 不能给常量赋值
1>c:\test\typedef.cpp(11): error C3892: “p2”: 不能给常量赋值

****
按我朋友的理解,const pStr p2 其中,const修辞的是pStr,而pStr类型实际上还是指针,所以这行是定义了一个常指针。可以理解为定义p2是指向char的常指针,常指针的话,p2++当然就不行。
***

============解释:4:
对  案例二  测试:

typedef.c:51:5: 错误: 向只读位置‘*p1’赋值
typedef.c:52:5: 错误: 令只读变量‘p2’自增

我对char * p的理解:两个部分,char为指向的值,p为指针变量,*只是做声明;
当const char * p1时,const修饰的是char,所以p1不能修改指向的值;
当const PStr p2时,const修饰的是p2,所以p2不能对自身做任何修改;

typedef相当于创建了一个新类型,只能做为整体来看。

============解释5:
其实,在这里主要就是对const的作用范围的理解。
typedef char * pStr;
char string1[4] = "abc";
char string2[4] = "def";
const char *p1 = string1;
const pStr p2 = string1;

p1[1] = 'f'; // 此句错
p1++; // 此句对
p1 = string2; // 此句对
p1[1] = 'x'; // 此句错

p2[1] = 'f'; // 此句对
p2++; // 此句错
p2 = string2; // 此句错

在const char *p1中,const的作用力量在p1所指的内容,也就是说,当p1指向string1时,string1的内容相对于p1来说是常量,是固定的,是不能改变的,所以p1[1] = 'f'这一句就是错误的,而p1自身的值(即地址值)是可以改变的,所以p1++和p1 = string2都是正确的。

在const pStr p2中,const的作用力量在p2,即p2是个常量,p2的值实际上是个地址,也就是说,p2已经固定了,它的值是不能变的,但它这个地址所指的内容是可以改变的,所以p2[1] = 'f'是对的,但p2 = string2是错误的,因为这句是想将另一个地址赋值给p2。

总体来说,一个是将内容固定为常量,一个是将地址固定为常量,也就是指针常量和常量指针的说法,p1是常量指针,p2是指针常量。这也是C中指针的魅力所在。

****插入语:
只看const 先不换typedef const修饰的是*p1 也就是说*p1这个值不能动 即不能赋值 const修饰的是p2,也就是说p2不能动 但*p2可以赋值

error C3892: 'p2' : you cannot assign to a variable that is const
看一下这个vs2008的错误就应该明白了吧,把这个类型当成系统定义的类型我觉得就比较好理解了,好比:
const int a = 5;
a++;
编译错误的道理是一样的。

******
大家共同进步哦~~

经典原文地址http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html

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. C++中typedef和define的区别

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

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

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

  8. typedef 与 define 的区别

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

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

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

随机推荐

  1. 《TCP/IP 详解 卷1:协议》第 5 章:Internet 协议

    IP 是 TCPIP 协议族中的核心协议.所有 TCP.UDP.ICMP.IGMP 数据都通过 IP 数据包(又称为 packet)来传输.IP 的英文名为 Internet Protocol,是互联 ...

  2. DispatcherServlet的作用

    DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好 ...

  3. java如何写入txt文件

    public class TxtWrite { public static void main(String args[]){ contentToTxt("D:\\xyky.txt" ...

  4. mongodb 下载安装 转

    MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...

  5. SQLSERVER STANDARD 版本不支持内存数据库

    1. 自己负责的一个环境 安装了 SQLSERVER2014 的 标准版 发现有问题. 恢复了一个带内存数据库的性能测试库之后报错. 报错信息很不明了,但是 查了半天发现必须升级企业版才可以... 还 ...

  6. C++的继承与多态

    ◆ 概念介绍 继承:为了代码的重用,保留基类的原本结构,并新增派生类的部分,同时可能覆盖(overide)基类的某些成员. 多态:一种将不同的特殊行为和单个泛化记号相关联的能力,分为静态多态和动态多态 ...

  7. myeclipse8.6 注册码

    MyEclipse8.6 注册码 别处找的均是8.6版本,可以使用到2014年一:MyEclipse Standard Edition: zhucemLR7ZL-655954-695876566190 ...

  8. Pythonの坑

    Python closures and late binding A closure occurs when a function has access to a local variable fro ...

  9. [Ispc2009]Let there be rainbows!

    Description HY Star是一个处处充满和谐,人民安居乐业的星球,但是HYStar却没有被评上宇宙文明星球,很大程度上是因为星球的形象问题. HY Star由N个国家组成,并且在一些国家之 ...

  10. codevs2464超级麻将

    题目链接http://codevs.cn/problem/2464/ 题目描述 Description 很多人都知道玩麻将,当然也有人不知道,呵呵,不要紧,我在这里简要地介绍一下麻将规则: 普通麻将有 ...