C指针太凌乱总弄不明白 求具体指点 (c指针有什么用)
本文目录导航:
C指针太凌乱总弄不明白,求具体指点
一、指针的算术运算指针可以加上或减去一个整数。
指针的这种运算的意义和理论的数值的加减运算的意义是不一样的,以单元为单位。
例如:例二:char a[20];int *ptr=(int *)a; //强迫类型转换并不会扭转a 的类型ptr++;在上例中,指针ptr 的类型是int*,它指向的类型是int,它被初始化为指向整型变量a。
接上去的第3 句中,指针ptr 被加了1,编译器是这样解决的:它把指针ptr 的值加上了sizeof(int),在32 位程序中,是被加上了4,由于在32 位程序中,int 占4 个字节。
由于地址是用字节做单位的,故ptr 所指向的地址由原来的变量a 的地址向洼地址方向参与了4 个字节。
由于char 类型的长度是一个字节,所以,原来ptr 是指向数组a 的第0 号元开局的四个字节,此时指向了数组a 中从第4 号单元开局的四个字节。
咱们可以用一个指针和一个循环来遍历一个数组,看例子:例三:int array[20]={0};int *ptr=array;for(i=0;i<20;i++){(*ptr)++;ptr++;}这个例子将整型数组中各个单元的值加1。
由于每次循环都将指针ptr加1 个单元,所以每次循环都能访问数组的下一个单元。
再看例子:例四:char a[20]=”You_are_a_girl”;int *ptr=(int *)a;ptr+=5;在这个例子中,ptr 被加上了5,编译器是这样解决的:将指针ptr 的值加上5 乘sizeof(int),在32 位程序中就是加上了5 乘4=20。
由于地址的单位是字节,故如今的ptr 所指向的地址比起加5 后的ptr 所指向的地址来说,向洼地址方向移动了20 个字节。
在这个例子中,没加5 前的ptr 指向数组a 的第0 号单元开局的四个字节,加5 后,ptr 曾经指向了数组a 的合法范畴之外了。
只管这种状况在运行上会出疑问,但在语法上却是可以的。
这也表现出了指针的灵敏性。
假设上例中,ptr 是被减去5,那么解决环节迥然不同,只不过ptr 的值是被减去5 乘sizeof(int),新的ptr 指向的地址将比原来的ptr 所指向的地址向低地址方向移动了20 个字节。
上方请准许我再举一个例子:(一个误区)例五:#includeint main(){char a[20]=” You_are_a_girl”;char *p=a;char **ptr=&p;//printf(”p=%d\n”,p);//printf(”ptr=%d\n”,ptr);//printf(”*ptr=%d\n”,*ptr);printf(”**ptr=%c\n”,**ptr);ptr++;//printf(”ptr=%d\n”,ptr);//printf(”*ptr=%d\n”,*ptr);printf(”**ptr=%c\n”,**ptr);}误区一、输入答案为Y 和o曲解:ptr 是一个char 的二级指针,当口头ptr++;时,会使指针加一个sizeof(char),所以输入如上结果,这个或许只是少局部人的结果.误区二、输入答案为Y 和a曲解:ptr 指向的是一个char *类型,当口头ptr++;时,会使指针加一个sizeof(char *)(有或许会有人以为这个值为1,那就会获取误区一的答案,这个值应该是4,参考前面内容), 即&p+4; 那启动一次性取值运算不就指向数组中的第五个元素了吗?那输入的结果不就是数组中第五个元素了吗?答案能否认的.正解: ptr 的类型是char **,指向的类型是一个char *类型,该指向的地址就是p的地址(&p),当口头ptr++;时,会使指针加一个sizeof(char*),即&p+4;那*(&p+4)指向哪呢,这个你去问上帝吧,或许他会通知你在哪?所以最后的输入会是一个随机的值,或许是一个合法操作.总结一下:一个指针ptrold 加(减)一个整数n 后,结果是一个新的指针ptrnew,ptrnew 的类型和ptrold 的类型相反,ptrnew 所指向的类型和ptrold所指向的类型也相反。
ptrnew 的值将比ptrold 的值参与(缩小)了n 乘sizeof(ptrold 所指向的类型)个字节。
就是说,ptrnew 所指向的内存区将比ptrold 所指向的内存区向高(低)地址方向移动了n 乘sizeof(ptrold 所指向的类型)个字节。
指针和指针启动加减:两个指针不能启动加法运算,这是合法操作,由于启动加法后,获取的结果指向一个不知所向的中央,而且毫有意义。
两个指针可以启动减法操作,但必定类型相反,普通用在数组方面,不多说了。
二、取地址运算符&和直接运算符*这里&是取地址运算符,*是直接运算符。
&a 的运算结果是一个指针,指针的类型是a 的类型加个*,指针所指向的类型是a 的类型,指针所指向的地址嘛,那就是a 的地址。
*p 的运算结果就不拘一格了。
总之*p 的结果是p 所指向的物品,这个物品有这些特点:它的类型是p 指向的类型,它所占用的地址是p所指向的地址。
例六:int a=12; int b; int *p; int **ptr;p=&a; //&a 的结果是一个指针,类型是int*,指向的类型是//int,指向的地址是a 的地址。
*p=24; //*p 的结果,在这里它的类型是int,它所占用的地址是//p 所指向的地址,显然,*p 就是变量a。
ptr=&p; //&p 的结果是个指针,该指针的类型是p 的类型加个*,//在这里是int **。
该指针所指向的类型是p 的类型,这//里是int*。
该指针所指向的地址就是指针p 自己的地址。
*ptr=&b; //*ptr 是个指针,&b 的结果也是个指针,且这两个指针//的类型和所指向的类型是一样的,所以用&b 来给*ptr 赋//值就是毫无疑问的了。
**ptr=34; //*ptr 的结果是ptr 所指向的物品,在这里是一个指针,//对这个指针再做一次性*运算,结果是一个int 类型的变量。
指针的算术运算,p+n和p-q各示意什么含意?
指针的算术运算是基于指针指向对象的空间大小来运算的。
从这个例子看,p自身是一个32位的int值,由于指向的是int型数据,因此p+1的实践地址值是参与了4
对于C言语指针的疑问
上方是我收藏的对于指针的一个十分好的文档,讲的很深化,楼关键是感兴味的话可以钻研一下,要是有疑问得中央可以随时问我。
。
。
第一章。
指针的概念 指针是一个不凡的变量,它外面存储的数值被解释成为内存里的一个地址。
要搞清一个指针须要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或许叫指针所指向的内存区,还有指针自身所占据的内存区。
让 咱们区分说明。
先申明几个指针放着做例子: 例一: (1)int *ptr; (2)char *ptr; (3)int **ptr; (4)int (*ptr)[3]; (5)int *(*ptr)[4]; 1。
指针的类型。
从语法的角度看,你只需把指针申明语句里的指针名字去掉,剩下的局部就是这个指针的类型。
这是指针自身所具备的类型。
让咱们看看例一中各个指针的 类型: (1)int *ptr; //指针的类型是int * (2)char *ptr; //指针的类型是char * (3)int **ptr; //指针的类型是 int ** (4)int (*ptr)[3]; //指针的类型是 int(*)[3] (5)int *(*ptr)[4]; //指针的类型是 int *(*)[4] 怎样样?找出指针的类型的方法是不是很便捷? 2。
指针所指向的类型。
当你经过指针来访问指针所指向的内存区时,指针所指向的类型选择了编译 器将把那片内存区里的内容当做什么来看待。
从语法上看,你只须把指针申明语句中的指针名字和名字左边的指针申明符 *去掉,剩下的就是指针所指向的类型。
例如: (1)int *ptr; //指针所指向的类型是int (2)char *ptr; //指针所指向的的类型是char (3)int **ptr; //指针所指向的的类型是 int * (4)int (*ptr)[3]; //指针所指向的的类型是 int()[3] (5)int *(*ptr)[4]; //指针所指向的的类型是 int *()[4] 在指针的算术运算中,指针所指向的类型有很大的作用。
指针的类型(即指针自身的类型)和指针所指向的类型是两个概念。
当你对C越 来越相熟时,你会发现,把与指针搅和在一同的类型这个概念分红指针的 类型和指针所指向的类型两个概念,是知晓指针的关键点之一。
我看了不 少书,发现有些写得差的书中,就把指针的这两个概念搅在一同了,所以看起书来前后矛盾,越看越懵懂。
3。
指针的值,或许叫指针所指向的内存区或地址。
指针的值是指针自身存储的数值,这个值将被编译器当作一个地址,而不是一个普通的数值。
在32位程序里,一切类型的指针的值都是一个32位整数,由于32位程序里内存地址全都是32位长。
指针所指向的内存区就是从指针的值所代表的那个内存地址开局,长度为sizeof(指针所指向的类型)的一片内存区。
以后,咱们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;咱们说一个指针指向了某块 内存区域,就相当于说该指针的值是这块内存区域的首地址。
指针所指向的内存区和指针所指向的类型是两个齐全不同的概念。
在例一中,指针所指向的类型曾经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或许说是有意义的。
以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的类型是什么?该指针指向了哪里? 4。
指针自身所占据的内存区。
指针自身占了多大的内存?你只需用函数sizeof(指针的类型)测一下就知道了。
在32位平台里,指针自身占据了4个字节的长度。
指针自身占据的内存这个概念在判别一个指针表白式能否是左值时很有用。
第二章。
指针的算术运算 指针可以加上或减去一个整数。
指针的这种运算的意义和理论的数值的加减运算的意义是不一样的。
例如: 例二: 1。
char a[20]; 2。
int *ptr=a; ... ... 3。
ptr++; 在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整 形变量a。
接上去的第3句中,指针ptr被加了1,编译器是这样解决的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。
由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向洼地址方向参与了4个字节。
由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开局的四个字节,此时指向了数组a中从第4号单元开局的四个字节。
咱们可以用一个指针和一个循环来遍历一个数组,看例子:例三: int array[20]; int *ptr=array; ... //此处略去为整型数组赋值的代码。
... for(i=0;i<20;i++) { (*ptr)++; ptr++; } 这个例子将整型数组中各个单元的值加1。
由于每次循环都将指针ptr加1,所 以每次循环都能访问数组的下一个单元。
再看例子: 例四: 1。
char a[20]; 2。
int *ptr=a; ... ... 3。
ptr+=5; 在这个例子中,ptr被加上了5,编译器是这样解决的:将指针ptr的值加上5 乘sizeof(int),在32位程序中就是加上了5乘4=20。
由于地址的单位是字节,故如今的ptr所指向的地址比起加5后的ptr所指向的地址来说,向洼地址方向移动了20个字节。
在这个例子中,没加5前的ptr指向数组a的第0号单元开局的四个字节,加5后,ptr曾经指向了数组a的合法范畴之外了。
只管这种状况在运行上会出疑问,但在语法上却是可以的。
这也表现出了指针的灵敏性。
假设上例中,ptr是被减去5,那么解决环节迥然不同,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。
总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相反,ptrnew所指向的类型和ptrold所指向的类型也相反。
ptrnew的值将比ptrold的值参与了n乘sizeof(ptrold所指向的类型)个字节。
就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向洼地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。
一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相反,ptrnew所指向的类型和ptrold所指向的类型也相反。
ptrnew的值将比ptrold的值缩小了n乘sizeof(ptrold所指向的类型)个字节,就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。
第三章。
运算?amp;和* 这里&是取地址运算符,*是...书上叫做直接运算符。
&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。
*p的运算结果就不拘一格了。
总之*p的结果是p所指向的物品,这个物品有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。
例五: int a=12; int b; int *p; int **ptr; p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址 是a的地址。
*p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地 址,显然,*p就是变量a。
ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int **。
该指针所指向的类型是p的类型,这里是int*。
该指针所指向的地址就是指针p自己的地址。
*ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所 指向的类型是一样的,所以用&b来给*ptr赋值就是毫无疑问的了。
**ptr=34;//*ptr的结果是ptr所指向的物品,在这里是一个指针,对这个指 针再做一次性*运算,结果就是一个int类型的变量。
第四章。
指针表白式。
一个表白式的最后结果假设是一个指针,那么这个表白式就叫指针表白式。
上方是一些指针表白式的例子: 例六: int a,b; int array[10]; int *pa; pa=&a;//&a是一个指针表白式。
int **ptr=&pa;//&pa也是一个指针表白式。
*ptr=&b;//*ptr和&b都是指针表白式。
pa=array; pa++;//这也是指针表白式。
例七: char *arr[20]; char **parr=arr;//假设把arr看作指针的话,arr也是指针表白式 char *str; str=*parr;//*parr是指针表白式 str=*(parr+1);//*(parr+1)是指针表白式 str=*(parr+2);//*(parr+2)是指针表白式 由于指针表白式的结果是一个指针,所以指针表白式也具备指针所具备的四个因素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。
好了,当一个指针表白式的结果指针曾经明白地具备了指针自身占据的内存的话,这个指针表白式就是一个左值,否则就不是一个左值。
在例七中,&a不是一个左值,由于它还没有占据明白的内存。
*ptr是一个左值,由于*ptr这个指针曾经占据了内存,其实*ptr就是指针pa,既然pa曾经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。
第五章。
数组和指针的相关 假设对申明数组的语句不太明白的话,请参阅我前段期间贴出的文?lt;<如何了解c和c++的复杂类型申明>>。
数组的数组名其实可以看作一个指针。
看下例: 例八: int array[10]={0,1,2,3,4,5,6,7,8,9},value; ... ... value=array[0];//也可写成:value=*array; value=array[3];//也可写成:value=*(array+3); value=array[4];//也可写成:value=*(array+4); 上例中,普通而言数组名array代表数组自身,类型是int [10],但假设把a rray看做指针的话,它指向数组的第0个单元,类型是int *,所指向的类型是数组单元的类型即int。
因此*array等于0就一点也不奇异了。
同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。
其它依此类推。
例九: char *str[3]={ Hello,this is a sample!, Hi,good morning., Hello world }; char s[80]; strcpy(s,str[0]);//也可写成strcpy(s,*str); strcpy(s,str[1]);//也可写成strcpy(s,*(str+1)); strcpy(s,str[2]);//也可写成strcpy(s,*(str+2)); 上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。
把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char *。
*str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串Hello,this is a sample!的第一个字符的地址,即’H’的地址。
str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char *。
*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向Hi,good morning.的第一个字符’H’,等等。
上方总结一下数组的数组名的疑问。
申明了一个数组TYPE array[n],则数组称号array就有了两重含意:第一,它代表整个数组,它的类型是TYPE [n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有独自的内存区,留意它和数组第0号单元占据的内存区是不同的。
该指针的值是不能修正的,即相似array++的表白式是失误的。
在不同的表白式中数组名array可以表演不同的角色。
在表白式sizeof(array)中,数组名array代表数组自身,故这时sizeof函数 测出的是整个数组的大小。
在表白式*array中,array表演的是指针,因此这个表白式的结果就是数组第0号单元的值。
sizeof(*array)测出的是数组单元的大小。
表白式array+n(其中n=0,1,2,....。
)中,array表演的是指针,故arr ay+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。
故sizeof(array+n)测出的是指针类型的大小。
例十: int array[10]; int (*ptr)[10]; ptr=&array; 上例中ptr是一个指针,它的类型是int (*)[10],他指向的类型是int [10] ,咱们用整个数组的首地址来初始化它。
在语句ptr=&array中,array代表数组自身。
本节中提到了函数sizeof(),那么我来问一问,sizeof(指针称号)测出的究 竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。
例如: int (*ptr)[10]; 则在32位程序中,有: sizeof(int(*)[10])==4 sizeof(int [10])==40 sizeof(ptr)==4 实践上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。
第六章。
指针和结构类型的相关 可以申明一个指向结构类型对象的指针。
例十一: struct MyStruct { int a; int b; int c; } MyStruct ss={20,30,40};//申明了却构对象ss,并把ss的三个成员初始 化为20,30和40。
MyStruct *ptr=&ss;//申明了一个指向结构对象ss的指针。
它的类型是 MyStruct*,它指向的类型是MyStruct。
int *pstr=(int*)&ss;//申明了一个指向结构对象ss的指针。
然而它的 类型和它指向的类型和ptr是不同的。
请问怎样经过指针ptr来访问ss的三个成员变量? 答案: ptr->a; ptr->b; ptr->c; 又请问怎样经过指针pstr来访问ss的三个成员变量? 答案: *pstr;//访问了ss的成员a。
*(pstr+1);//访问了ss的成员b。
*(pstr+2)//访问了ss的成员c。
呵呵,只管我在我的MSVC++6.0上调式过上述代码,然而要知道,这样经常使用p str来访问结形成员是不正轨的,为了说明为什么不正轨,让咱们看看怎样经过指 针来访问数组的各个单元: 例十二: int array[3]={35,56,37}; int *pa=array; 经过指针pa访问数组array的三个单元的方法是: *pa;//访问了第0号单元 *(pa+1);//访问了第1号单元 *(pa+2);//访问了第2号单元 从格局上看倒是与经过指针访问结形成员的不正轨方法的格局一样。
一切的C/C++编译器在陈列数组的单元时,总是把各个数组单元寄存在延续的存储区里,单元和单元之间没有空隙。
但在寄存结构对象的各个成员时,在某种编译环境下,或许会须要字对齐或双字对齐或许是别的什么对齐,须要在相邻两个成员之间加若干?quot;填充字节,这就造成各个成员之间或许会有若干个字节的空隙。
所以,在例十二中,即使*pstr访问到了却构对象ss的第一个成员变量a,也不能保障*(pstr+1)就必定能访问到结形成员b。
由于成员a和成员b之间或许会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。
这也证实了指针的灵敏性。
要是你的目标就是想看看各个结形成员之间究竟有没有填充字节, 嘿,这倒是个不错的方法。
经过指针访问结形成员的正确方法应该是象例十二中经常使用指针ptr的方法。
第七章。
指针和函数的相关 可以把一个指针申明成为一个指向函数的指针。
int fun1(char*,int); int (*pfun1)(char*,int); pfun1=fun1; .... .... int a=(*pfun1)(abcdefg,7);//经过函数指针调用函数。
可以把指针作为函数的形参。
在函数调用语句中,可以用指针表白式来作为 实参。
例十三: int fun(char*); int a; char str[]=abcdefghijklmn; a=fun(str); ... ... int fun(char*s) { int num=0; for(int i=0;i { num+=*s;s++; } return num; ) 这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。
前面说了,数组的名字也是一个指针。
在函数调用中,当把str作为实参传递给形参s后,实践是把str的值传递给了s,s所指向的地址就和str所指向的地址分歧,然而str和s各自占用各自的存储空间。
在函数体内对s启动自加1运算,并不象征着同时对str启动了自加1运算。
第八章。
指针类型转换 当咱们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的左边是一个指针表白式。
在咱们前面所举的例子中,绝大少数状况下,指针的类型和指针表白式的类型是一样的,指针所指向的类型和指针表白式所指向的类型是一样的。
例十四: 1。
float f=12.3; 2。
float *fptr=&f; 3。
int *p; 在上方的例子中,假设咱们想让指针p指向实数f,应该怎样搞?是用上方的语句吗? p=&f; 不对。
由于指针p的类型是int*,它指向的类型是int。
表白式&f的结果是一 个指针,指针的类型是float*,它指向的类型是float。
两者不分歧,直接赋值的方法是不行的。
至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两头的类型分歧,所指向的类型也分歧,其它的编译器上我没试过,大家可以试试。
为了成功咱们的目标,须要启动强迫类型转换: p=(int*)&f; 假设有一个指针p,咱们须要把它的类型和所指向的类型改为TYEP*和TYPE, 那么语法格局是: (TYPE*)p; 这样强迫类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。
而原来的指针p的一切属性都没有被修正。
一个函数假设经常使用了指针作为形参,那么在函数调用语句的实参和形参的联合环节中,也会出现指针类型的转换。
例十五: void fun(char*); int a=125,b; fun((char*)&a); ... ... void fun(char*s) { char c; c=*(s+3);*(s+3)=*(s+0);*(s+0)=c; c=*(s+2);*(s+2)=*(s+1);*(s+1)=c; } } 留意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。
函数fun的作用是把一个整数的四个字节的顺序来个颠倒。
留意到了吗?在函数调用语句中,实参&a的结果是一个指针,它的类型是int *,它指向的类型是int。
形参这个指针的类型是char*,它指向的类型是char。
这样,在实参和形参的联合环节中,咱们必定启动一次性从int*类型到char*类型的转换。
联合这个例子,咱们可以这样来构想编译器启动转换的环节:编译器先结构一个暂时指针 char*temp,而后口头temp=(char*)&a,最后再把temp的值传递给s。
所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。
咱们曾经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。
那可无法以把一个整数当作指针的值直接赋给指针呢?就象上方的语句: unsigned int a; TYPE *ptr;//TYPE是int,char或结构类型等等类型。
... ... a=; ptr=;//咱们的目标是要使指针ptr指向地址(十进制 ) ptr=a;//咱们的目标是要使指针ptr指向地址(十进制) 编译一下吧。
结果发现前面两条语句全是错的。
那么咱们的目标就不能到达了吗?不,还有方法: unsigned int a; TYPE *ptr;//TYPE是int,char或结构类型等等类型。
... ... a=某个数,这个数必定代表一个合法的地址; ptr=(TYPE*)a;//呵呵,这就可以了。
严厉说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。
这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。
上方强调了a的值必定代表一个合法的地址,否则的话,在你经常使用ptr的时刻,就会出现合法操作失误。
想想能不能反上来,把指针指向的地址即指针的值当作一个整数取进去。
齐全可以。
上方的例子展示了把一个指针的值当作一个整数取进去,而后再把这个整数当作一个地址赋给一个指针: 例十六: int a=123,b; int *ptr=&a; char *str; b=(int)ptr;//把指针ptr的值当作一个整数取进去。
str=(char*)b;//把这个整数的值当作一个地址赋给指针str。
好了,如今咱们曾经知道了,可以把指针的值当作一个整数取进去,也可以把一个整数值当作地址赋给一个指针。
第九章。
指针的安保疑问 看上方的例子: 例十七: char s=’a’; int *ptr; ptr=(int*)&s; *ptr=1298; 指针ptr是一个int*类型的指针,它指向的类型是int。
它指向的地址就是s的首地址。
在32位程序中,s占一个字节,int类型占四个字节。
最后一条语句岂但扭转了s所占的一个字节,还把和s相临的洼地址方向的三个字节也扭转了。
这三个字节是干什么的?只要编译程序知道,而写程序的人是不太或许知道的。
兴许这三个字节里存储了十分关键的数据,兴许这三个字节里正好是程序的一条代码,而由于你对指针的马虎运行,这三个字节的值被扭转了!这会形成解体性的失误。
让咱们再来看一例: 例十八: 1。
char a; 2。
int *ptr=&a; ... ... 3。
ptr++; 4。
*ptr=115; 该例子齐全可以经过编译,并能口头。
然而看到没有?第3句对指针ptr启动自加1运算后,ptr指向了和整形变量a相邻的洼地址方向的一块存储区。
这块存储区里是什么?咱们不知道。
有或许它是一个十分关键的数据,甚至或许是一条代码。
而第4句居然往这片存储区里写入一个数据!这是重大的失误。
所以在经常使用指针时,程序员心里必定十分分明:我的指针终究指向了哪里。
在用指针访问数组的时刻,也要留意不要超出数组的低端和上流界限,否则也会形成相似的失误。
在指针的强迫类型转换:ptr1=(TYPE*)ptr2中,假设sizeof(ptr2的类型)大 于sizeof(ptr1的类型),那么在经常使用指针ptr1来访问ptr2所指向的存储区时是安保的。
假设sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在经常使用指针ptr1来访问ptr2所指向的存储区时是不安保的。
至于为什么,读者联合例十七来想一想,应该会明白的。