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. 【搜索】POJ-3669 BFS

    一.题目 Description Bessie hears that an extraordinary meteor shower is coming; reports say that these ...

  2. 16_常用API_第16天(正则表达式、Date、DateFormat、Calendar)_讲义

    今日内容介绍 1.正则表达式的定义及使用 2.Date类的用法 3.Calendar类的用法 ==========================================第一阶段======= ...

  3. Gradle入门(4):依赖管理

    在现实生活中,要创造一个没有任何外部依赖的应用程序并非不可能,但也是极具挑战的.这也是为什么依赖管理对于每个软件项目都是至关重要的一部分. 这篇教程主要讲述如何使用Gradle管理我们项目的依赖,我们 ...

  4. vue之Mutations 理解

    commit:提交可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 stor ...

  5. Android bp语法介绍

    参考网址: http://note.qidong.name/demo/soong_build/ 谷歌官网文档: https://android.googlesource.com/platform/bu ...

  6. [转帖] 学习一下 apache bench 的总结简介 ( LAMP的没用过..)

    PS:网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压情况下才能真正体现出各种设置所暴露的问题.Apache中有个自带的,名为ab的程序,可以对Apache或其它类型的服务器进行网 ...

  7. js 小程序获取本周七天

    data: { weekdays:['','','','','','',''] },     onLoad: function (options) { let that = this; let now ...

  8. Angular js Radio Button

    症状: 绑定一个list   radio button 老是只能绑定一行,纠结了很久 ,回家发现  原来是 name 用了同一个  ,坑啊,记录下 免得下次再犯. 之前的代码 <ul> & ...

  9. Java的StringBuIlder扩容机制

    JDK 1.6中,扩容的源码是这样: void expandCapacity(int minimumCapacity) { int newCapacity = (value.length + 1) * ...

  10. DAY3-Flask项目

    1.jsonify: 得到了从API获得的数据并返回,API返回的json数据被转化成dict,我们还需要把dict序列化: return json.dump(result), 200, {'cont ...