与c ++中的&(* a)操作,反直觉?

时间:2012-10-01 18:32:55

标签: c++

在此代码中:

  int* a;
  int* b;
  int c;
  int* d;
  a=new int(5);
  b=&(*a);
  c=*a;
  d=&c;
  cout<<"*a = "<<*a<<endl;
  cout<<"a = "<<a<<endl;
  cout<<"b ="<<b<<endl;
  cout<<"d = "<<d<<endl;

我明白了:

*a = 5
 a = 0x83a2008
 b =0x83a2008
 d = 0xbfbfe540

为什么d与b不同?他们俩都不是&amp;(* a)?如何用一行得到d结果?

非常感谢。

7 个答案:

答案 0 :(得分:7)

a指向动态分配的位置,保持值为5.执行c = *a;时,您将 5从动态分配的位置复制到{ {1}}。然后,您将获取c的地址并将其分配给c(并将其打印出来)。

当你最终得到的是这样的:

enter image description here

实线表示指向位置的指针。虚线表示数据的移动。

答案 1 :(得分:6)

c是它自己的int而不是int*。当您说c = *a时,您实际上是将a指向的值分配给内存中具有自己空间的单独整数(即使此int不是int* },它仍然必须存在于内存中。)

因此,当您说d = &c时,您获得的地址为c,而不是a的地址。

答案 2 :(得分:1)

d = &c;

d指向c指定的存储位置,该位置不是a指向的存储位置。

答案 3 :(得分:1)

d是c的地址,它是本地堆栈变量。 b是您在堆上分配的整数的地址,并将地址存储在。

答案 4 :(得分:1)

c是整数的新实例,这就是d不等于ab的原因。因此,当您尝试获取存储在a中的值的地址时,您会获得a的确切地址。但是,当您首先将a的值分配给c然后打印c的地址时,您获得的地址与a不同。在C ++中,您对真实对象进行操作,而不是像Java或C#中那样引用。当您为变量赋值时,您复制存储在此变量中的每个字段,但要小心 - 默认情况下=运算符不进行深度克隆。

答案 5 :(得分:1)

我认为C11 / C99第6.5.3.2节第4段和脚注102中有一些内容

  

指向由其操作数指定的对象或函数的指针。该   一元*运算符表示间接。如果操作数指向a   功能,结果是功能指示符;如果它指向一个   对象,结果是指定对象的左值。 如果是操作数   类型''指向类型'',结果类型为''type''。如果   无效值已分配给指针,行为   unary * operator is undefined .02)

脚注102告诉

  

102)因此,&amp; * E等效于E(即使E是空指针),   &amp;(E1 [E2])至((E1)+(E2))。如果E是一个函数,那总是如此   指示符或左值运算符的有效操作数的左值,   *&amp; E是函数指示符或等于E的左值。如果* P是左值而T是对象指针类型的名称,*(T)P是左值   具有与T指向的类型兼容的类型。之间   一元*运算符取消引用指针的值无效   一个空指针,一个不恰当地对齐类型的地址   object指向的对象,以及对象结束后的地址   一生。是&amp;

修改 c = *a;将导致未定义的行为,因为未分配内存位置5。

答案 6 :(得分:0)

我不知道所有的规则和细微之处,但编译器能够将&(*a)简化为a。因此,您要初始化b以指向a指向(b = a)的相同整数。然后,您将按值将整数复制到c。然后,您正在初始化d以指向c。因此ab指向相同的整数,但d指向其他整数。