搜索
bottom↓
回复: 16

C语言灵魂的请教

[复制链接]

出0入0汤圆

发表于 2010-10-12 14:07:08 | 显示全部楼层 |阅读模式
char *p1;
char *p2;
p2 = *(char **)p1;  

请问指针p1与p2是一样吗?

我的理解:首先(char **)p1 把p1转化为字符型的二级指针,再通过最前面的*转化为一级指针,也就可以付值给p2了。给感觉就好像是p2 = p1;可现实并不是这么简单。还请大侠指点迷津。先谢了!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-10-12 14:12:42 | 显示全部楼层
不是p2=p1;
个人认为应该是将p1地址中的内容给p2

楼下继续

出0入0汤圆

发表于 2010-10-12 14:35:55 | 显示全部楼层
实质是p2 = * p1
(char **)是为了类型匹配,即char * = *(char **)。

出0入93汤圆

发表于 2010-10-12 14:39:08 | 显示全部楼层
当然不一样。

调试一下什么都明白了,主要注意一下p1、p2、*p1、&p2的值。
当然,p2 = *(char **)p1; 这句本身就是有问题的,调试不见得会通过(编译是没有问题的),可能非法访问内存。

出0入0汤圆

发表于 2010-10-12 16:33:34 | 显示全部楼层
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

出0入0汤圆

发表于 2010-10-12 16:39:39 | 显示全部楼层
回复【2楼】dr2001
实质是p2 = * p1
(char **)是为了类型匹配,即char * = *(char **)。
-----------------------------------------------------------------------

谁说的char * = *(char **)?注意(char **)只不过是转换,而不是取址

出0入0汤圆

 楼主| 发表于 2010-10-12 16:54:13 | 显示全部楼层
回复【3楼】takashiki 岚月影
当然不一样。
调试一下什么都明白了,主要注意一下p1、p2、*p1、&p2的值。
当然,p2 = *(char **)p1; 这句本身就是有问题的,调试不见得会通过(编译是没有问题的),可能非法访问内存。
-----------------------------------------------------------------------

我这里发帖请教的就是想搞清楚这个“当然”不一样了。肯定是主要注意一下p1、p2、*p1、&p2的值,但主要这个转换过程是怎么样的?还请takashiki 大侠能不能细说?
另外 p2 = *(char **)p1;这句话有没有问题不不知道,在VC++2010,Win-Tc ,MDK3.5,都试过没有编译问题,也没有警告的。

出0入0汤圆

发表于 2010-10-12 16:57:47 | 显示全部楼层
假设char * 与int占用存储空间大小一样

p2 = *(char **)p1;   
可理解为:

p2= (char *)(*(int *)p1)

出0入0汤圆

发表于 2010-10-12 17:05:37 | 显示全部楼层
回复【6楼】zhangxun0712  
-----------------------------------------------------------------------

不严格的说,强制类型转换就是告诉编译器:把这个变量在这里临时看做这个类型,然后完成表达式计算。

研究代码执行的操作的时候,
可以首先忽略强制类型转换部分,去看代码执行什么样的操作,如直接赋值,取地址,取值,etc;
然后,依据强制类型转换后的类型,确定具体执行什么样的操作。

出0入0汤圆

发表于 2010-10-12 17:09:45 | 显示全部楼层
mark

出0入93汤圆

发表于 2010-10-12 17:15:57 | 显示全部楼层
不管对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;
}

出0入93汤圆

发表于 2010-10-12 17:21:27 | 显示全部楼层
回复【8楼】dr2001  
回复【6楼】zhangxun0712  
-----------------------------------------------------------------------
不严格的说,强制类型转换就是告诉编译器:把这个变量在这里临时看做这个类型,然后完成表达式计算。
研究代码执行的操作的时候,
可以首先忽略强制类型转换部分,去看代码执行什么样的操作,如直接赋值,取地址,取值,etc;
然后,依据强制类型转换后的类型,确定具体执行什么样的操作。

-----------------------------------------------------------------------

这个确实太不严格了……不要这么理解。
double<->float,double<->int及所有int兼容类型,float<->int及所有int兼容类型都改变了变量本身的值。
“把这个变量在这里临时看做这个类型,然后完成表达式计算。”这个得用联合体完成。

出0入0汤圆

发表于 2010-10-12 18:40:02 | 显示全部楼层
先看看
char��*p1;
char��*p2;
p2��=��*p1;
你说p1=p2么?当然不一样这个不用解释了吧
但这时编译器就告诉你类型不匹配了啥办?
于是就有了
char��*p1;
char��*p2;
p2��=��*(char��**)p1;  
强制类型匹配,编译是通过了但由于乱用指针会导致运行时非法读取内存。

出0入9汤圆

发表于 2010-10-12 19:57:44 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-10-13 08:45:14 | 显示全部楼层
谢谢各位大侠的热心解答与指导,特别是takashiki。跟据你说的,我又回去看了看,指针,二级指针,指针数组,基本上是懂了。
我给的例子不全导制分析出现了一点点偏差。情况是当*p1指向一个指针型的数组的地址时,如char *str[]={"one","two","three"};时p1指向的是字符串"one"地址的地址,而p2则指向的是存取字符串"one"的首地址,输出printf("%s",p2)为one. 表达能力不好,不知说清楚了没有。

出0入0汤圆

发表于 2010-10-13 09:14:08 | 显示全部楼层
指针也是变量,自己也有地址

出0入0汤圆

发表于 2010-10-13 09:14:19 | 显示全部楼层
p2 = *(char **)p1;   
p1是什么,就是一个地址,一串数字,这个不关键,主要还是要把这串数字转化成什么的数据类型
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-16 06:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表