递增指针输出

huangapple go评论58阅读模式
英文:

Incrementing Pointers Output

问题

y在指向下一个位置,其值为32561时为什么是20?以及为什么y++会改变事情?

y指向下一个位置的值为32561,但y的值仍然是20的原因是y++是一个后缀递增操作符,它首先使用y的当前值(20),然后再将y递增到下一个位置。所以在这一行代码int a = *y++;执行后,a被分配了y当前的值,也就是20,然后*y递增到下一个位置。

随后的递增操作导致*y指向了下一个位置,但这个位置的值是32561。这就是为什么在接下来的操作中,y和e的值都是32561。

递增操作符y++和y的不同之处在于前者在使用当前值后再递增指针,而后者先递增指针然后再使用新的指针位置的值。所以在你的代码中,y++导致了指针y移动到下一个位置,而*y保持在之前的位置,因此它们引用不同的内存位置,从而导致不同的值。

英文:

I have the following C code.

#include<stdio.h>
  
int main()
{
    int x = 20, *y, *z;
      
    y = &x; // y points to x 
    z = y; // z points to x
    printf("Value at &x=%d &x+1=%d &x+2=%d &x+3=%d\n",x,*(&x+1),*(&x+2),*(&x+3));
    printf("Initial addresses: &x=%p, y=%p z=%p\n",&x,y,z);
    int a = *y++;   
    printf("a=%d y=%p *y=%d\n",a,y,*y);
    printf("y=%p *y=%d\n",y,*y);
    int e = *y++;    
    printf("e=%d y=%p *y=%d\n",e,y,*y);
    printf("y=%p *y=%d\n",y,*y);
    *y++;
    printf("y=%p *y=%d\n",y,*y);
    int b = *y; 
    int c = *z++;  
    int d = *z; 
    x++; 
    printf("x = %d, y = %p, z = %p ,address of x = %p\n", x, y, z,&x);
    printf("a = %d, b = %d, e=%d, c = %d, d = %d\n",a,b,e,c,d);
    return 0;
}

The output is

Value at &x=20 &x+1=32561 &x+2=-149757104 &x+3=21894
Initial addresses: &x=0x7fff9afe5570, y=0x7fff9afe5570 z=0x7fff9afe5570
a=20 y=0x7fff9afe5574 *y=20
y=0x7fff9afe5574 *y=20
e=20 y=0x7fff9afe5578 *y=20
y=0x7fff9afe5578 *y=20
y=0x7fff9afe557c *y=21894
x = 21, y = 0x7fff9afe557c, z = 0x7fff9afe5574 ,address of x = 0x7fff9afe5570
a = 20, b = 21894, e=20, c = 20, d = 20

Why *y is 20 when it points to the next location where the value is 32561?
Also why *y++ then changes things.

I tried changing the flow and added more print statements.

答案1

得分: 0

嘿,指针存储变量的地址。但是在代码中声明的两个变量不一定会相邻,它们分配在内存的不同部分。
如果您想要内存连续分配,最好声明一个数组,内存将以连续的方式分配,并将指针分配给基础地址,然后移动到下一个位置。

英文:

Hey pointer stores address of the variable .But there is no rule that two variables declared in code will be consecutive next they are allocated in different parts of memory.
If you want memory in consecutive manner than better declare an array memory will be allocated continuous manner and assign pointer to base address and move to next

答案2

得分: 0

执行这行代码后:

int a = *y++; 

y 变成了一个无效指针1,并且对无效指针进行解引用的行为是未定义的2;实际上可能会得到任何结果,包括你期望的结果。

如果你期望变量按特定顺序排列,请不要这样做 — 编译器不要求按照你声明它们的顺序进行排列3,并且根据堆栈的增长方式,它们可能按照你期望的相反顺序排列。

我的特定系统中,堆栈是"向下"增长的,x 是所有变量中地址最的。在执行该行代码后,内存中的项目如下所示:

       项目         地址   00   01   02   03
       ----         -------   --   --   --   --
          x     0x16f4c3720   14   00   00   00    ....

          y     0x16f4c3718   24   37   4c   6f    $7Lo
                0x16f4c371c   01   00   00   00    ....

          z     0x16f4c3710   20   37   4c   6f    .7Lo
                0x16f4c3714   01   00   00   00    ....

          a     0x16f4c370c   14   00   00   00    ....

          b     0x16f4c3708   10   00   00   00    ....

          c     0x16f4c3704   01   00   00   00    ....

          d     0x16f4c3700   40   80   94   00    @...

          e     0x16f4c36fc   01   00   27   03    ..'.

"Nothing"4 存在于地址 0x16f4c3724,这是递增 y 的结果。*y 的值可能是任何值,而且可能会在不同运行中发生变化。

你不能将指针设置为任意值并期望得到有意义的结果。获取有效指针值的唯一方式是:

  • 使用一元操作符 & 在左值上(例如,变量名如 &x,数组下标表达式如 &a[i],成员选择表达式如 &s.m&sp->m 等)。

  • 调用返回指针值的库函数,如 malloccallocreallocfopen 等。


  1. 在该对象的生命周期内不再指向该对象。
  2. 这意味着编译器和运行时环境都不要求以任何特定方式处理这种情况。
  3. 除了结构体定义中的成员。
  4. 我的意思是任何用户定义的对象(变量,数组,等等);你可能碰到了堆栈帧的帧指针或返回地址。
    英文:

    After you execute this line:

    int a = *y++; 
    

    y becomes an invalid pointer<sup>1</sup>, and the behavior on dereferencing an invalid pointer is undefined<sup>2</sup>; literally any result is possible, including the result you expect.

    If you're expecting variables to be laid out in a specific order, don't &mdash; the compiler is not required to lay them out in the same order you declared them<sup>3</sup>, and depending on how your stack grows they may be laid out in the opposite order you expect.

    On my particular system the stack grows "downwards", and x has the highest address of all the variables. After you execute that line, this is what your items in memory look like:

           Item         Address   00   01   02   03
           ----         -------   --   --   --   --
              x     0x16f4c3720   14   00   00   00    ....
    
              y     0x16f4c3718   24   37   4c   6f    $7Lo
                    0x16f4c371c   01   00   00   00    ....
    
              z     0x16f4c3710   20   37   4c   6f    .7Lo
                    0x16f4c3714   01   00   00   00    ....
    
              a     0x16f4c370c   14   00   00   00    ....
    
              b     0x16f4c3708   10   00   00   00    ....
    
              c     0x16f4c3704   01   00   00   00    ....
    
              d     0x16f4c3700   40   80   94   00    @...
    
              e     0x16f4c36fc   01   00   27   03    ..&#39;.
    

    "Nothing"<sup>4</sup> lives at address 0x16f4c3724, which would be the result of incrementing y. The value of *y could be anything, and it could change from run to run.

    You can't set pointers to arbitrary values and expect anything meaningful. The only ways to obtain valid pointer values are:

    • using the unary &amp; operator on an lvalue (i.e., variable name like &amp;x, array subscript expression like &amp;a[i], member selection expression like &amp;s.m or &amp;sp-&gt;m, etc.).

    • calling a library function that returns a pointer value such as malloc, calloc, realloc, fopen, etc.

    <hr>
    <sup>
    <ol>
    <li>It is no longer pointing an object during that object's lifetime.
    <li>Meaning that neither the compiler nor the runtime environment are required to handle the situation in any particular way.
    <li>Except for members in a <code>struct</code> definition.
    <li>By which I mean any user-defined object (variable, array, whatever); you're likely bumping into the frame pointer or return address of the stack frame.
    </ol>
    </sup>

huangapple
  • 本文由 发表于 2023年7月3日 19:29:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76604308.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定