C 中的指针和地址

发布于 2024-09-03 19:53:56 字数 941 浏览 2 评论 0原文

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

#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 编译器

The following code manipulates pointers to point at the same location; I'm puzzled about why when I ran the code, the output didn't show value coinciding.

#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);  
}  

Output:

Address of x= 3219901868
Address of y= 3219901860
Address of z= 3219901875
New Address of x= 3219901872
New Address of y= 3219901876
New Address of z= 3219901876
New Value of i= 3
New Value of j= 1.500000
New Value of k= c

The new address of variable y and z are same. How can two variables have same address and et have different values?
Note: I used gcc compiler on Ubuntu 9.04

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情绪少女 2024-09-10 19:53:56

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

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

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

What you are printing is not the address of x/y/z, but rather the address they are pointing at. Then, by modifying the pointers (using ++) you eventually get y and z to point at the same address in memory.

Regarding the values - first thing you should notice that you don't actually change the values of j and k, and by the time you print those values the pointers no longer point to them.

Second thing is, even if you did print the value that the pointers point to, you would still get a different value since in one case the data would be interpreted as a float and in the other as a char.

°如果伤别离去 2024-09-10 19:53:56

啊。指针算术的危险。

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

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

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

如果您将“j”定义为浮点数组,它将指向数组中相当于 j[1] 的第二个条目。值得一提的是,C 也允许你使用 j[1],即使你没有将 j 定义为数组!

Ah. The dangers of pointer arithmatic.

So y = &j sets pointer y to tha current address of float "j"

then you say y++ as you have defined y as a float pointer this is interpreted as add the length of a float variable to pointer y.

However you have only defined one floating point "j" so y is now pointing at whatever has been allocated after "j" -- in this case it happens to be the address of the "k" variable which was defined immediatly after -- but in practice it could be anything or nothing.

Had you defined "j" as an array of floating points it would have pointed to the second entry in the array equivalent to j[1]. Incendently C will also allow you to use j[1] even though you have not defined j as an array!

裸钻 2024-09-10 19:53:56

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

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

  • 递增 char 指针将在地址上加 1
  • 递增长指针将在地址上加 4(在具有long 为 4 个字节)
  • 等等

Incrementing pointers this way is only useful if your pointer points to an element in an array.

In fact, incrementing a pointer just increases its value by the size indicated by the type of the pointer, so:

  • incrementing a char-pointer will add 1 to the address
  • incrementing a long-pointer will add 4 to the address (on systems where a long is 4 bytes)
  • and so on
清君侧 2024-09-10 19:53:56

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

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

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

Also, while it is not the case in your examples, two variables may (appear to) have the same address but different values.
Assuming that you did:

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);
}

.. you could theoretically end up with the same address shown for both x and y (if you turn on optimization) . Because the parameter of "display_addr_and_val" is a const reference, the code can be rewritten as:

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);
}

now, in this version of the code, you may see that there is no overlap in the lifetime of "x" and "y". Which means that in fact the compiler may choose to use the same stack slot for both of them.

Granted, this doesn't happen very often, but there's not theoretical reason why it shouldn't happen - so the bottom line is that you should use extreme caution when you assume anything about the address of variables - especially local ones (e.g. don't assume that their addresses will be allocated in a given order, or that all distinct variables will use distinct addresses)

迷你仙 2024-09-10 19:53:56

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

你有 y + 16 = z + 1 这并不奇怪,记住“下一个浮点数”(y现在指向的“东西”)确实不是浮点数,而是之后的内存位置浮点数,对于 z 也是如此(它不会指向一个字符);

它只是意味着 float 位置位于 char 位置“之前”15 个字节。即y+15=z。

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

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

It's simple pointer math.
the address of the float is incremented at least by sizeof(float), (it should be 4 but you have an increment of 16, it depends on the hardware and the real size used to store floats) while the address of char is incremented by sizeof(char) (1)

you have that y + 16 = z + 1 which is not surprising, remembering that "the next float" (the "things" y now points to) is not indeed a float, but the memory location after the float and so it is for z (it'll point not to a char);

it just means that the float location is 15 bytes "before" the char location. I.e. y + 15 = z.

EDIT: with y I always mean the address of the float taken with &, and so for z...: i.e. before you incrmented them. y+16 is the incremented value of y (after you did y++) and z+1 the incremented value of z after z++.

EDIT 2: dumb me, I did not note that you increment y 4 times! so sizeof(float) is 4, 4*4= 16 ... ! and it is 4 on your machine too (as expected by IEEE for single precision fp numbers...) and so it means that y + (sizeof(float)*4 = z + sizeof(char) ... it still means y location is 15 bytes before z (the address of the char)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文