C中的指针和地址

时间:2010-06-03 07:03:14

标签: c programming-languages pointers

以下代码操纵指向同一位置的指针;我很困惑为什么当我运行代码时,输​​出没有显示值重合。

#include "stdio.h"  
main()  
{  
int i=3,*x;  
float j=1.5,*y;  
char k='c',*z;  

x=&i;  
y=&j;  
z=&k;  

printf("\nAddress of x= %u",x);  
printf("\nAddress of y= %u",y);  
printf("\nAddress of z= %u",z);  

x++;  
y++;y++;y++;y++;  
z++;  

printf("\nNew Address of x= %u",x);  
printf("\nNew Address of y= %u",y);  
printf("\nNew Address of z= %u",z);  

printf("\nNew Value of i= %d",i);  
printf("\nNew Value of j= %f",j);  
printf("\nNew Value of k= %c\n",k);  
}  

输出:

  

地址x = 3219901868
  地址y = 3219901860
  地址z = 3219901875
  新地址x = 3219901872
  新地址y = 3219901876
  新地址z = 3219901876
  i = 3的新值   新值j = 1.500000
  新值k = c

变量y和z的新地址相同。两个变量如何具有相同的地址,并且具有不同的值? 注意:我在Ubuntu 9.04上使用了gcc编译器

5 个答案:

答案 0 :(得分:12)

您要打印的内容不是x / y / z的地址,而是它们指向的地址。然后,通过修改指针(使用++),最终得到y和z指向内存中的相同地址。

关于值 - 首先你应该注意到你实际上没有改变j和k的值,并且当你打印这些值时,指针不再指向它们。

第二件事是,即使你确实打印了指针指向的值,你仍然会得到一个不同的值,因为在一种情况下,数据将被解释为一个浮点数而另一个被解释为一个char。

答案 1 :(得分:0)

只有当指针指向数组中的元素时,以这种方式递增指针才有用。

实际上,递增指针只会将其值增加指针类型指示的大小,因此:

  • 递增一个char-pointer会将1加到地址
  • 递增一个长指针将为地址添加4(在长为4字节的系统上)

答案 2 :(得分:0)

阿。指针算术的危险性。

所以y = &j将指针y设置为浮动“j”的当前地址

然后你说y++因为你已经将y定义为浮点指针,这被解释为将浮点变量的长度添加到指针y。

但是你只定义了一个浮点“j”,所以y现在指向“j”之后已经分配的任何东西 - 在这种情况下,它恰好是“k”变量的地址,该变量是在立即定义的 - 但实际上它可以是任何东西。

如果将“j”定义为浮点数组,则它将指向数组中与j [1]等效的第二个条目。即使你没有将j定义为一个数组,Incendently C也允许你使用j [1]!

答案 3 :(得分:0)

此外,虽然您的示例中不是这种情况,但两个变量可能(看起来)具有相同的地址但值不同。 假设你做了:

void display_addr_and_val(const int& var){
  printf("Addr:%p  Val:%d\n",&var, var);
}

void main(){
int x=0;
int y=1;

display_addr_and_val(x);
display_addr_and_val(y);
}

..理论上你可以得到x和y所示的相同地址(如果打开优化)。因为“display_addr_and_val”的参数是const引用,所以代码可以重写为:

void display_addr_and_val(const int& var){
  printf("Addr:%p  Val:%d\n",&var, var);
}

void main(){
int x=0;
display_addr_and_val(x);

int y=1;
display_addr_and_val(y);
}

现在,在此版本的代码中,您可能会发现“x”和“y”的生命周期中没有重叠。这意味着实际上编译器可能会选择为它们使用相同的堆栈槽。

当然,这种情况不会经常发生,但理论上没有理由说明为什么不应该发生 - 所以最重要的是,当你假设有关地址时,你应该格外小心变量 - 尤其是本地变量(例如,不要假设它们的地址将按给定的顺序分配,或者所有不同的变量将使用不同的地址)

答案 4 :(得分:0)

这是简单的指针数学。 float的地址至少增加了sizeof(float),(它应该是4,但你的增量为16,它取决于硬件和用于存储浮点数的实际大小),而char的地址增加了sizeof(char)(1)

你有y + 16 = z + 1这并不奇怪,记住“下一个浮动”(现在指向的“事物”)确实不是浮点数,而是浮点数后的内存位置等等它适用于z(它不会指向char);

它只是意味着浮点位置在char位置“之前”为15个字节。即y + 15 = z。

编辑:y,我总是指用&取得的浮点数的地址,因此对于z ...:即在你加入它们之前。 y + 16是y的递增值(在你执行y ++之后)和z + 1在z ++之后递增的z值。

编辑 2:愚蠢的我,我没有注意到你增加了4倍! sizeof(float)是4,4 * 4 = 16 ......!在你的机器上它也是4(正如IEEE对单精度fp数字的预期...)所以它意味着y +(sizeof(float)* 4 = z + sizeof(char)......它仍然意味着y位置是z之前的15个字节(字符的地址)