作为函数返回的指针不会像声称的那样被覆盖

时间:2015-04-19 00:02:31

标签: c function pointers return

声称这里的代码不会返回正确的“Sum”,因为前面的PrintHelloWorld()正在执行并取代了指针*ptr所指向的值。但是,每次运行它时都会得到正确的值,甚至在PrintHelloWorld()打印之前运行*ptr函数十几次。

那么为什么我的代码工作并返回值,即使指针指向一个已声明从堆栈中弹出的值?

#include <stdio.h>
#include <stdlib.h>

void PrintHelloWorld()
{
    printf("Hello World\n");
}

int *Add(int *a, int *b)
{
    int c = (*a) + (*b);
    return &c;
}

int main()
{
    int a = 2, b = 4;
    int *ptr = Add(&a,&b);
    PrintHelloWorld();
    printf("Sum = %d\n", *ptr);

    return 0;
}

2 个答案:

答案 0 :(得分:2)

这被称为Undefined Behavior并且它未定义,因此任何事情都可能发生,您无法实际预测行为,因为它取决于程序的结构及其运行条件。

如果启用编译警告,编译器必须警告您错误,返回本地变量的地址并尝试读取它的内容是未定义的行为,因为它在您从函数返回时已经解除分配。

由于它的未定义行为,任何事情都可能发生,例如,它可以正常工作&#34; 正确&#34;。

您正在返回本地变量的地址。存储c结果的变量*a + *b是函数Add()的本地变量,并且具有自动存储持续时间。

这意味着,当函数返回时,它将被取消分配。由于您已将地址返回给它,并且已取消分配,因此尝试打印它只会输出垃圾。

试试这个,看看

int *Add(int a, int b, int *c)
 {
    *c = a + b;
    return c;
 } 

然后在main()

int main()
 {
    int a = 2, b = 4, c, *ptr;
    ptr = Add(a, b, &c);
    printf("Sum = %d\n", *ptr);

    return 0;
 }

如您所见,您通过了c的地址并在Add()函数内对其进行了修改。

c变量是main()的本地变量,因此将其地址传递给Add()修改它,然后在main()中读取它是完全可以的,因为在main()它仍然有效。

只有当它超出范围时才会被解除分配,在这种情况下没有发生。

答案 1 :(得分:0)

当您编写表现出未定义行为的代码时,发生未定义行为并不令人惊讶。使用特定体系结构上特定操作系统上的特定编译器,视频中的人正在使用它,他获得了你在那里看到的输出。

对于其他编译器,您可能会遇到其他形式的未定义行为。

例如,每次我尝试在计算机上运行时,此代码都会打印不同的输出值:

#include <stdio.h>
#include <stdlib.h>

int *Add(int *a, int *b)
{
    int c = (*a) + (*b);
    return &c;
}

int main()
{
    int a = 2, b = 4;
    int *ptr = Add(&a,&b);
    printf("Sum = %d\n", *ptr);
}

一些运行:

[7:15pm][wlynch@watermelon /tmp] ./a.out
Sum = 1595243208
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1392249544
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1577798344
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1340385992
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1549621960
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1572055752
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1440946888
[7:16pm][wlynch@watermelon /tmp] ./a.out
Sum = 1604803272