in cmainframe::cmainframe()
{  int a = 1,b=2,c=3;
 int* p;
 memcpy(&p+4,&b,4);
}
_DEBUG下出错,RELEASE不出错。
memcpy执行后,this指针变成2了,为什么?
我发现stack是从高地址到低地址的,&p+4就是c的地址,但memcpy后,c的值没有变成2,为什么?memcpy到底在什么地方写入了4字节的什么内容?

解决方案 »

  1.   

    int a = 1,b=2,c=3;
     int* p;
     memcpy(&p+4,&b,4);说真的,看不懂你这写的什么,是不是错的太多了```
    1.p指针没有给初值,
    2.p的指针地址做什么用~??
      

  2.   

    你用&c看一下变量c的地址不就明白了么。
      

  3.   

    _DEBUG下出错,RELEASE不出错。
    memcpy执行后,this指针变成2了,为什么?在Debug下, 结果与你说的一致 int a = 1,b=2,c=3;
    在Release下代码优化后 a, c 变量没有使用, 被编译器删除
    变量b为常量, 被常量替换, 变量b也不存在了in cmainframe::cmainframe()
    类构造函数 会对this指针操作, 可能会用到this指针, 可能把b就写入到this, 所以成2memcpy到底在什么地方写入了4字节的什么内容?
    这问题有很大的不确定性
      

  4.   

    这个应该和编译器有关吧,结果是不确定的,我试了一下,Debug运行的结果是
    &a = 0x0012f9dc, &b = 0x0012f9d0, &c = 0x0012f9c4, &p = 0x0012f8b8, &this = 0x0012f9e8, 那么可以推算出&p+4 = 0x0012f9c8,而这个地址也并不是this指针的地址,也不是c的地址。
    在不同的编译器和不同的编译环境,结果相同的概率几乎为0。对于这种不确定的问题,就没有讨论的必要了。
      

  5.   

    hehe 转C/C++新手乐园 ^_^: )
      

  6.   

    w_anthony() 的实例跟我的实例有差别:
    &a = 0x0012f9dc, &b = 0x0012f9d0, &c = 0x0012f9c4, &p = 0x0012f8b8, &this = 0x0012f9e8,我的是:
    &a = 0x0012fe28,&b = 0x0012fe24, &c = 0x0012fe20, &p = 0012fe1c,&p+4 = 0x0012fe20,
    以4字节为单位,而他的怎么会是以12字节为单位呢?sizeof(int)应该是4。
    那么你改成memcpy(&p+12,&b,4)看看,c的值会不会改变?
      

  7.   

    如果&p = 0012fe1c,那么&p+4 = 0x0012fe2c,而不是0x0012fe20
      

  8.   

    如果是p+4的话,比如p是0x0...1c,那么p+4是0x0...2c没错,因为p是int类型的指针
    而lz那种情况里面则就是0x0...20,也就是直接加4的结果,因为这里&p取得是一个地址,而给这个地址单纯加4就不会像int那样计算,可以试下直接&(p+4),编译器就慌了,因为不知道是啥,本来就没分配这个东西~~~~~,当然,更重要的个原因就是他用的vc6
    而ls估计用的vs 2005
    2005我前几天刚用,根本闹不明白
    不过lz的那个在2005上倒是没太大问题,按ls给的地址,memecpy自己肯定是不成了,那就改为
    &p+3吧,然后发现...,c的value变了,而且是拷贝了4个b,而不是4字节,也就是说,得改成
    memcpy(&p+3,b,1),这样,c就变成2了........(*@&#)(*@&#)(@*&#,就是说要是memcpy(&p+3,b,4)的话,c就变成了0x02020202.........
    虽然的确是lz写的不对,编译器不同,开关不同也造成了不可预知的情况,但是这个... ...
      

  9.   

    LS在说什么?难道你认为&p+4等同于&(p+4)?memcpy(void*,const void*,size_t),难道这参数还能知道你的参数1是指4个字节不成?另外我用的是2003,memcpy和pointer + n对哪个编译器都一样,只是LZ的这个问题依赖于编译器,没什么好讨论的。
      

  10.   

    呵呵,当然不是等同于&(p+4)了,要不也不会让你试,因为&(p+4)是根本无法得到结果的我的意思是说在用(p+4)这个表达式的时候,两个编译器是一样的,因为p是int *
    而在使用&p+4的时候就不一样,vc6是直接加上4,而我用的2005则是和你的结果一样
    还有,最好测试一下,别太武断
      

  11.   

    如果是p是int类型,那么&p就是int*,int*的加4肯定是偏移16个字节的啊,比如int*的++,肯定就是偏移4个字节,无论用什么编译都应该一样,不然就没有可移植性了。
    VC6加4就直接加4?虽然没有VC6可以测试,但我也绝对不信。
    LZ认为是直接加4,但实际上却并不是直接加4,错误就在这里……
      

  12.   

    谢谢大家测试,是我犯了一个小错误:
    int* p,我把&p给理解成了int类型,实际上不是,也怪vc6的watch窗口欺骗了我,watch里的&p+4的确是在&p的基础上只加了4个字节。所以不能完全相信它。我从反汇编发现就是偏移了16字节,和watch结果不同,所以我没有搞懂。把代码改一下:
    int a = 1,b = 2;
    //把b的值赋值给a
    int* p;
    memcpy( ((char*)&p) + ((int)&a-(int)&p),&b,4);所以指针在没有初始化的情况下仍然有用途。