一个关于指针于引用以及数组向退化的问题

snailman 2011-08-30 05:45:57

typedef void* LPVOID;

struct Para
{
int i[1];
}

void func(void*& p)
{

}
int main(int, char**)
{
//! 下面代码有些是编译期问题,有些是运行期问题
//! 一一指出
Para p1;
func((void*&)(&p1));
func((void*&)(p1.i));

const LPVOID& cLPVoidRef0 = (const LPVOID&)(&p1);
const LPVOID& cLPVoidRef1 = (const LPVOID&)(p1.i);

LPVOID& LPVoidRef0 = (LPVOID&)(&p1);
LPVOID& LPVoidRef1 = (LPVOID&)(p1.i);


const void*& cVoidRef0 = (const void*&)(&p1);
const void*& cVoidRef1 = (const void*&)(p1.i);

void*const& cVoidRef0 = (void*const&)(&p1);
void*const& cVoidRef1 = (void*const&)(p1.i);

void*& voidRef0 = (void*&)(&p1);
void*& voidRef1 = (void*&)(p1.i);

void* pTemp= &p1;
const void* cpTemp = &p1;
void* const cpvoidTemp = &p1;

const void*& cVoidRefTemp0 = pTemp;
const void*& cVoidRefTemp0Ex = pTemp;

const void*& cVoidRefTemp1 = cpTemp;
void* const& cVoidRefTemp1Ex = cpTemp;

return 0;
}

...全文
128 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
PG 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zhao4zhong1 的回复:]

为什么要有数据结构这个东东?
因为要将现实世界或者抽象理论中的各种数据保存在计算机外存(光盘、硬盘、U盘……)或内存(ROM、RAM、SRAM……)里面的一维二进制字节数组中。
然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。
[/Quote]

顶起...
zxzxghgh 2011-08-31
  • 打赏
  • 举报
回复
指针即地址
引用即别名
赵4老师 2011-08-31
  • 打赏
  • 举报
回复
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要写连自己也预测不了结果的代码!
赵4老师 2011-08-31
  • 打赏
  • 举报
回复
为什么要有数据结构这个东东?
因为要将现实世界或者抽象理论中的各种数据保存在计算机外存(光盘、硬盘、U盘……)或内存(ROM、RAM、SRAM……)里面的一维二进制字节数组中。
然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。
赵4老师 2011-08-31
  • 打赏
  • 举报
回复
指针即地址
引用即别名

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!
PG 2011-08-31
  • 打赏
  • 举报
回复
擂鼓呐喊,助威~!
snailman 2011-08-31
  • 打赏
  • 举报
回复
有星星和勋章以及牛逼的人哪去老,赶紧出来啊
snailman 2011-08-31
  • 打赏
  • 举报
回复
其实这个问题是我在写服务器代码遇到的一个问题,所引发出来的。所以我写了上面代码用来测试我的想法,在我贴出的代码中,部分可以理解,有些不是很清楚,所以贴出来让大家给出解释,然后加深对这方面知识的理解。不清楚的部分如下,忘大家指点:
//1. C2012:要求左值,这个可以理解
void*& voidRef0 = (void*&)(&p1);

//2. 这个是执行期错误,那么编译器对这个代码是怎么处理的:(比较疑惑的)
void*& voidRef1 = (void*&)(p1.i);
汇编码如下:
lea eax,[p1]
mov dword ptr[voidRef1], eax

//3. 下面这个是正确的,也可以理解
void*const& cVoidRef1 = (void*const&)(p1.i);
汇编码如下:
lea eax,[p1]
mov dword ptr[ebp-1A0h],eax
lea ecx,[ebp-1A0h]
mov dword ptr[cVoidRef1], ecx


请大家解释一下情况2,编译器是怎么处理的;比较情况2于情况3编译器处理的不同之处。

snailman 2011-08-31
  • 打赏
  • 举报
回复
其实这个问题是我在写服务器代码遇到的一个问题,所引发出来的。所以我写了上面代码用来测试我的想法,在我贴出对这部分代码中,我以理解,有些不是很清楚,所以贴出来让大家给出解释,然后加深对这方面知识的理解。不清楚的部分如下,忘大家指点:
//1. C2012:要求左值,这个可以理解
void*& voidRef0 = (void*&)(&p1);

//2. 这个是执行期错误,那么编译期对这个代码是怎么处理的:(比较疑惑的)
void*& voidRef1 = (void*&)(p1.i);
汇编码如下:
lea eax,[p1]
mov dword ptr[voidRef1], eax

//3. 下面这个是正确的,也可以理解
void*const& cVoidRef1 = (void*const&)(p1.i);
汇编码如下:
lea eax,[p1]
mov dword ptr[ebp-1A0h],eax
lea ecx,[ebp-1A0h]
mov dword ptr[cVoidRef1], ecx


请大家解释一下情况2,实在怎么编译器的;比较情况2于情况3编译器处理的不同之处。




snailman 2011-08-31
  • 打赏
  • 举报
回复
还是自己来吧。结贴
至善者善之敌 2011-08-30
  • 打赏
  • 举报
回复
我是来帮顶的~
healer_kx 2011-08-30
  • 打赏
  • 举报
回复

const void*& cVoidRefTemp0 = pTemp;
const void*& cVoidRefTemp0Ex = pTemp;
这两个的原因就是因为 pTemp 是非 const的。加上const修饰就好了。


至于这个:
void* const& cVoidRefTemp1Ex = cpTemp;
就根本不对路了。。。
你看看这个:
http://www.cppblog.com/kredraw/archive/2008/10/04/63211.aspx

healer_kx 2011-08-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 dizuo 的回复:]

这一票 甘草上吧。
[/Quote]
。。。 。。。
ningto.com 2011-08-30
  • 打赏
  • 举报
回复

typedef void* LPVOID;

struct Para
{
int i[1];
};

void func(void*& p)
{

}

int main(int, char**)
{
Para p1;
func((void*&)(p1));
func((void*&)(p1.i));

const LPVOID& cLPVoidRef0 = (const LPVOID&)(&p1);
const LPVOID& cLPVoidRef1 = (const LPVOID&)(p1.i);

LPVOID& LPVoidRef0 = (LPVOID&)(p1);
LPVOID& LPVoidRef1 = (LPVOID&)(p1.i);


const void*& cVoidRef0 = (const void*&)(p1);
const void*& cVoidRef1 = (const void*&)(p1.i);

void*const& cVoidRef00 = (void*const&)(p1);
void*const& cVoidRef11 = (void*const&)(p1.i);

void*& voidRef0 = (void*&)(p1);
void*& voidRef1 = (void*&)(p1.i);

void* pTemp= &p1;
const void* cpTemp = &p1;
void* const cpvoidTemp = &p1;

const void*& cVoidRefTemp0 = (const void *&)pTemp;
const void*& cVoidRefTemp0Ex = (const void *&)pTemp;

const void*& cVoidRefTemp1 = cpTemp;
void* const& cVoidRefTemp1Ex = (void* const&)cpTemp;

getchar();
return 0;
}
ryfdizuo 2011-08-30
  • 打赏
  • 举报
回复
这一票 甘草上吧。
healer_kx 2011-08-30
  • 打赏
  • 举报
回复
LPVOID& LPVoidRef0 = (LPVOID&)(&p1);
const void*& cVoidRef0 = (const void*&)(&p1);
void*& voidRef0 = (void*&)(&p1);
同4楼。都是左值的问题
healer_kx 2011-08-30
  • 打赏
  • 举报
回复
func((void*&)(&p1));
这个的编译错误是:error C2102: “&”要求左值

这个简单吧? 因为&p1是p1的地址,一个对象的地址怎么可能是左值呢?




snailman 2011-08-30
  • 打赏
  • 举报
回复
别啊,啥结贴率,解释清楚代码立即给分。
healer_kx 2011-08-30
  • 打赏
  • 举报
回复
这么复杂。。。
weixiaoshashou 2011-08-30
  • 打赏
  • 举报
回复
对LZ的结贴率表示困惑。。。

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧