C语言灵魂的请教
char *p1;char *p2;
p2 = *(char **)p1;
请问指针p1与p2是一样吗?
我的理解:首先(char **)p1 把p1转化为字符型的二级指针,再通过最前面的*转化为一级指针,也就可以付值给p2了。给感觉就好像是p2 = p1;可现实并不是这么简单。还请大侠指点迷津。先谢了! 不是p2=p1;
个人认为应该是将p1地址中的内容给p2
楼下继续 实质是p2 = * p1
(char **)是为了类型匹配,即char * = *(char **)。 当然不一样。
调试一下什么都明白了,主要注意一下p1、p2、*p1、&p2的值。
当然,p2 = *(char **)p1; 这句本身就是有问题的,调试不见得会通过(编译是没有问题的),可能非法访问内存。 p1本来是一个地址,他可以是8、16或32位(假设是16位,假设为0x1234),而指向的是8位,假设位0x56
(char **)p1,是把一个(char *)型的指针强制转换为(char **)p1,值还是0x1234,指向的就不是char了,而是一个指针,指针是16位的,就只能是指向0x56和后面一个未知的数了。
现在你硬要来个*(char **)p1,那没办法,给你取数了,只不过取的不是8位了(因(char **)p1的值是16位的),而是16位的,所以就取了0x56和后面一个数,0x56和后面一个数组成一个指针给p2 回复【2楼】dr2001
实质是p2 = * p1
(char **)是为了类型匹配,即char * = *(char **)。
-----------------------------------------------------------------------
谁说的char * = *(char **)?注意(char **)只不过是转换,而不是取址 回复【3楼】takashiki 岚月影
当然不一样。
调试一下什么都明白了,主要注意一下p1、p2、*p1、&p2的值。
当然,p2 = *(char **)p1; 这句本身就是有问题的,调试不见得会通过(编译是没有问题的),可能非法访问内存。
-----------------------------------------------------------------------
我这里发帖请教的就是想搞清楚这个“当然”不一样了。肯定是主要注意一下p1、p2、*p1、&p2的值,但主要这个转换过程是怎么样的?还请takashiki 大侠能不能细说?
另外 p2 = *(char **)p1;这句话有没有问题不不知道,在VC++2010,Win-Tc ,MDK3.5,都试过没有编译问题,也没有警告的。 假设char * 与int占用存储空间大小一样
p2 = *(char **)p1;
可理解为:
p2= (char *)(*(int *)p1) 回复【6楼】zhangxun0712
-----------------------------------------------------------------------
不严格的说,强制类型转换就是告诉编译器:把这个变量在这里临时看做这个类型,然后完成表达式计算。
研究代码执行的操作的时候,
可以首先忽略强制类型转换部分,去看代码执行什么样的操作,如直接赋值,取地址,取值,etc;
然后,依据强制类型转换后的类型,确定具体执行什么样的操作。 mark 不管对p1、p2、*p1、&p2中哪一个指针来说,它们底层都是一个整型的数值。那么就有:
p2 = *(char **)p1;这种强制转换并没有改变数据,也就是(char**)p1和p1的底层是一样的,那么p2只不过是对p1取值而已。因此:
p2 = *p1
p1 = &p2
p2 = *(char **)p1;可能存在运行时问题的,编译可以通过,但运行就不见得了。
比如,在VC上,p1 = NULL;这句没有问题的语句,在经过*(char**)p1之后就变成对0地址取值了,就会因为内存非法访问而出错。一般来说,对于一级指针,我们总是尽量避免让它指向非法地址;而二级指针则应该避免它自身以及它指向的值指向非法地址,比较容易出错一些,将一级指针强制转换成二级指针时更容易出错。
VC++2010,Win-Tc ,MDK3.5,都很好软件调试的,设个断点,监视一下这些就行了。在PC上,至少0地址是被保护的,取它的值会出错;ARM上,访问不存在的内存应该会引起数据访问异常。
看一下VC下面出错的代码:
#include "stdafx.h"
int main(int argc, char* argv[])
{
char *p1 = 0; //没有用的指针指向0地址,因为p1可能会随时改变,这里我就特意赋值0了
char *p2;
p2 = *(char **)p1; //非法访问p1地址了,调试时会产生异常的
printf("Hello World!\n");
return 0;
} 回复【8楼】dr2001
回复【6楼】zhangxun0712
-----------------------------------------------------------------------
不严格的说,强制类型转换就是告诉编译器:把这个变量在这里临时看做这个类型,然后完成表达式计算。
研究代码执行的操作的时候,
可以首先忽略强制类型转换部分,去看代码执行什么样的操作,如直接赋值,取地址,取值,etc;
然后,依据强制类型转换后的类型,确定具体执行什么样的操作。
-----------------------------------------------------------------------
这个确实太不严格了……不要这么理解。
double<->float,double<->int及所有int兼容类型,float<->int及所有int兼容类型都改变了变量本身的值。
“把这个变量在这里临时看做这个类型,然后完成表达式计算。”这个得用联合体完成。 先看看
char��*p1;
char��*p2;
p2��=��*p1;
你说p1=p2么?当然不一样这个不用解释了吧
但这时编译器就告诉你类型不匹配了啥办?
于是就有了
char��*p1;
char��*p2;
p2��=��*(char��**)p1;
强制类型匹配,编译是通过了但由于乱用指针会导致运行时非法读取内存。 mark 谢谢各位大侠的热心解答与指导,特别是takashiki。跟据你说的,我又回去看了看,指针,二级指针,指针数组,基本上是懂了。
我给的例子不全导制分析出现了一点点偏差。情况是当*p1指向一个指针型的数组的地址时,如char *str[]={"one","two","three"};时p1指向的是字符串"one"地址的地址,而p2则指向的是存取字符串"one"的首地址,输出printf("%s",p2)为one. 表达能力不好,不知说清楚了没有。 指针也是变量,自己也有地址 p2 = *(char **)p1;
p1是什么,就是一个地址,一串数字,这个不关键,主要还是要把这串数字转化成什么的数据类型
页:
[1]