繁体   English   中英

C中的指针和地址

[英]Pointers and Addresses in C

下面的代码操纵指针指向同一位置; 我为为什么在运行代码时输出的显示值不一致而感到困惑。

#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的新地址相同。 两个变量如何具有相同的地址,而et如何具有不同的值? 注意:我在Ubuntu 9.04上使用了gcc编译器

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

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

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

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

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

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

啊。 指针算术的危险。

因此y = &j将指针y设置为浮点“ j”的当前地址

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

但是,您仅定义了一个浮点“ j”,因此y现在指向在“ j”之后分配的任何内容-在这种情况下,它恰好是“ k”变量的地址,该地址在之后立即定义-但实际上,它可以是任何东西或什么都不是。

如果将“ j”定义为浮点数组,它将指向数组中等于j [1]的第二个条目。 即使您尚未将j定义为数组,C也会允许您使用j [1]!

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

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”的生存期没有重叠。 这意味着实际上编译器可能会选择对它们两个使用相同的堆栈插槽。

当然,这种情况并不经常发生,但是没有理论上的理由不应该发生这种情况-因此,最重要的是,当您假设有关变量地址的任何信息时,尤其是局部变量(例如,不要使用' t假设它们的地址将按照给定的顺序分配,或者所有不同的变量都将使用不同的地址)

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

您有y + 16 = z + 1,这不足为奇,请记住“下一个浮点数”(y现在指向的“事物”)实际上并不是浮点数,而是浮点数之后的内存位置,因此z(它不会指向一个字符);

它仅表示float位置在char位置之前“ 15个字节”。 即y + 15 = z。

编辑 :与y我总是用&表示浮点数的地址,对于z ...也是如此:即在增加它们之前。 y + 16是y的增量值(在执行y ++之后),而z + 1是z ++的增量值。

编辑 2:愚蠢的我,我没有注意到您增加y 4倍! 所以sizeof(float)是4,4 * 4 = 16 ...! 并且它在您的计算机上也为4(如IEEE期望的单精度fp数...),因此这意味着y +(sizeof(float)* 4 = z + sizeof(char)...仍然表示y位置在z(字符的地址)之前15个字节

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM