简体   繁体   English

解释 output

[英]Explain the output

#include<stdio.h>

int * fun(int a1,int b)
{
    int a[2];
    a[0]=a1;
    a[1]=b;
    return a;
}
int main()
{
    int *r=fun(3,5);
    printf("%d\n",*r);
    printf("%d\n",*r);
}

Output after running the code: Output 运行代码后:

3
-1073855580

I understand that a[2] is local to fun() but why value is getting changed of same pointer?我知道 a[2] 是 fun() 本地的,但为什么值会改变同一个指针?

The variable a is indeed local to fun.变量 a 确实很有趣。 When you return from that function, the stack is popped.当您从该 function 返回时,堆栈被弹出。 The memory itself remains unchanged (for the moment). memory 本身保持不变(目前)。 When you dereference r the first time, the memory is what you'd expect it to be.当您第一次取消引用 r 时,memory 就是您所期望的。 And since the dereference happens before the call to printf, nothing bad happens.由于取消引用是在调用 printf之前发生的,因此不会发生任何不好的事情。 When printf executes, it modifies the stack and the value is wiped out.当 printf 执行时,它会修改堆栈并且值被擦除。 The second time through you're seeing whatever value happened to be put there by printf the first time through.第二次通过时,您会看到第一次通过 printf 时发生的任何值。

The order of events for a "normal" calling convention (I know, I know -- no such thing): “正常”调用约定的事件顺序(我知道,我知道 - 没有这样的事情):

  • Dereference r (the first time through, this is what it should be)解引用r (第一次通过,应该是这个)
  • Push value onto stack (notice this is making a copy of the value) (may wipe out a)将值压入堆栈(注意这是复制值)(可能会清除 a)
  • Push other parameters on to stack (order is usually right to left, IIRC) (may wipe out a)将其他参数推入堆栈(顺序通常是从右到左,IIRC)(可能会清除 a)
  • Allocate room for return value on stack (may wipe out a)在堆栈上为返回值分配空间(可能会清除 a)
  • Call printf致电 printf
  • Push local printf variables onto stack (may wipe out a)将本地 printf 变量推入堆栈(可能会清除 a)
  • Do your thang做你的事情
  • Return from function从 function 返回

If you change int a[2];如果你改变int a[2]; to static int a[2];static int a[2]; this will alleviate the problem.这将缓解问题。

Because r points to a location on the stack that is likely to be overwritten by a function call.因为r指向堆栈上可能被 function 调用覆盖的位置。

In this case, it's the first call to printf itself which is changing that location.在这种情况下,这是对printf本身的第一次调用,它正在更改该位置。

In detail, the return from fun has that particular location being preserved simply because nothing has overwritten it yet.详细地说,从fun的返回具有保留该特定位置的原因仅仅是因为尚未覆盖它。

The *r is then evaluated (as 3) and passed to printf to be printed.然后评估*r (作为 3)并传递给printf以进行打印。 The actual call to printf changes the contents of that location (since it uses the memory for its own stack frame), but the value has already been extracted at that point so it's safe.printf的实际调用会更改该位置的内容(因为它使用 memory 作为自己的堆栈帧),但该值已经在此时提取,因此它是安全的。

On the subsequent call, *r has the different value, changed by the first call.在随后的调用中, *r具有不同的值,由第一次调用更改。 That's why it's different in this case.这就是为什么在这种情况下有所不同。

Of course, this is just the likely explanation.当然,这只是可能的解释。 In reality, anything could be happening since what you've coded up there is undefined behaviour.实际上,任何事情都可能发生,因为您在那里编写的代码是未定义的行为。 Once you do that, all bets are off.一旦你这样做了,所有的赌注都没有了。

When you compile you code with the following command:当您使用以下命令编译代码时:

$ gcc -Wall yourProgram.c 

It will yield a warning, which says.它会产生一个警告,上面写着。

In function ‘fun’:
warning: function returns address of local variable

When r is dereferenced in first printf statement, it's okay as the memory is preserved.在第一个r语句中取消引用printf时,可以保留 memory。 However, the second printf statement overwrites the stack and so we get an undesired result.但是,第二个printf语句覆盖了堆栈,因此我们得到了不希望的结果。

As you've mentioned, a[2] is local to fun() ;正如您所提到的, a[2]fun()本地的; meaning it is created on the stack right before the code within fun() starts executing.这意味着它是在fun()中的代码开始执行之前在堆栈上创建的。 When fun exits the stack is popped , meaning it is unwound so that the stack pointer is pointing to where it was before fun started executing.fun退出时,堆栈被弹出,这意味着它被展开,因此堆栈指针指向它在fun开始执行之前的位置。

The compiler is now free to stick whatever it wants into those locations that were unwound.编译器现在可以自由地将任何它想要的东西粘贴到那些未展开的位置。 So, it is possible that the first location of a was skipped for a variety of reasons.因此,由于各种原因,可能会跳过a的第一个位置。 Maybe it now represents an uninitialized variable.也许它现在代表一个未初始化的变量。 Maybe it was for memory alignment of another variable.也许是另一个变量的 memory alignment。 Simple answer is, by returning a pointer to a local variable from a function, and then de-referencing that pointer, you're invoking undefined behavior and anything can happen, including demons flying out of your nose .简单的答案是,通过从 function 返回指向局部变量的指针,然后取消引用该指针,您正在调用未定义的行为并且任何事情都可能发生,包括恶魔飞出你的鼻子

Because printf is using the stack location and changes it after printing the first value.因为 printf 正在使用堆栈位置,并在打印第一个值后更改它。

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

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