C printf更改值

C printf更改值,c,function,pointers,printf,C,Function,Pointers,Printf,考虑一下这个小代码 #include <stdio.h> #include <stdlib.h> void* foo1(double bar) { double s2 = 0.5; double s1 = bar/s2; double toreturn[2] = {s1,s2}; printf("Outside main. Second value: %f\n", toreturn[1]); //this line is commente

考虑一下这个小代码

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

void* foo1(double bar)
{
    double s2 = 0.5;
    double s1 = bar/s2;
    double toreturn[2] = {s1,s2};
    printf("Outside main. Second value: %f\n", toreturn[1]); //this line is commented out for the second output. See below text
    return toreturn;
}


int main()
{
    void* (*foo)(double) = NULL;
    foo = &foo1;
    double bar = 2.12;

    double* resp = foo(bar);
    printf("In main. First value: %f\n", resp[0]);
    printf("In main. Second value: %f\n", resp[1]);
    return 0;
}
,这正是我所期望的。但是,如果我将print指令注释掉,即foo1定义中的指令,我将得到以下输出:

In main. First value: 4.240000
In main. Second value: 0.000000

,这对我来说毫无意义!printf命令可以更改变量的值,这在我看来似乎很奇怪。你能解释一下吗?请解释一下这种行为?

这里的要点是,你不能从函数返回本地数组。在函数调用之后,数组toreturn使用的内存是可用的。它可以被任何函数调用覆盖,包括printf


使用malloc为函数中的数组分配内存,并返回指向已分配内存的指针,或将数组作为参数传递。

这里的要点是,不能从函数返回本地数组。在函数调用之后,数组toreturn使用的内存是可用的。它可以被任何函数调用覆盖,包括printf

使用malloc为函数中的数组分配内存,并返回指向已分配内存的指针,或将数组作为参数传递。

您将向堆栈上分配的数组返回一个void*。一旦函数foo1返回,该内存将不再分配,因此使用resp from main是未定义的行为

打印resp[0]或resp[1]是没有意义的,您不应该期望任何特定的输出,因为您有未定义的行为

如果要在main中使用该数组,应在main中声明该数组,并将指向该数组的指针作为参数传递给函数:

double resp[2];
foo(bar, resp);
void foo1(double bar, double* resp)
{
    double s2 = 0.5;
    double s1 = bar/s2;

    resp[0] = s1;
    resp[1] = s2;
}
具有以下功能:

double resp[2];
foo(bar, resp);
void foo1(double bar, double* resp)
{
    double s2 = 0.5;
    double s1 = bar/s2;

    resp[0] = s1;
    resp[1] = s2;
}
或者,您可以使用malloc在foo1内部分配它,并返回一个指向该分配内存的指针,但您需要一种很好的方法来跟踪对malloc的每次调用,以便在完成后可以调用free。

您将向堆栈上分配的数组返回一个void*。一旦函数foo1返回,该内存将不再分配,因此使用resp from main是未定义的行为

打印resp[0]或resp[1]是没有意义的,您不应该期望任何特定的输出,因为您有未定义的行为

如果要在main中使用该数组,应在main中声明该数组,并将指向该数组的指针作为参数传递给函数:

double resp[2];
foo(bar, resp);
void foo1(double bar, double* resp)
{
    double s2 = 0.5;
    double s1 = bar/s2;

    resp[0] = s1;
    resp[1] = s2;
}
具有以下功能:

double resp[2];
foo(bar, resp);
void foo1(double bar, double* resp)
{
    double s2 = 0.5;
    double s1 = bar/s2;

    resp[0] = s1;
    resp[1] = s2;
}


或者,您可以使用malloc在foo1内部分配它,并返回一个指向该分配内存的指针,但您需要一种很好的方法来跟踪对malloc的每次调用,以便在完成后可以自由调用。

尝试%lf而不是%fAlso,toreturn是当函数返回时消失的局部变量。@Charlie Burns注意:double或float的printf使用说明符%lf或%f打印相同的内容。这必须是新的。。。就像在过去20年中一样。这是因为浮点数在参数列表中被提升为双精度浮点数吗?请尝试%lf而不是%fAlso,toreturn是一个局部变量,当函数返回时会消失。@Charlie Burns注意:double或float的printf使用说明符%lf或%f打印相同的值。这必须是新的。。。就像在过去的20年里。这是因为浮点数在参数列表中被提升为双倍数吗?不是静态分配的,堆栈分配如果是静态分配的,那很好不是线程安全,而是很好。它是本地分配的。@pm100:是的。更准确地说,它具有自动存储时间。谢谢Paulpro。你还回答了我在下面删除的评论@atycnth的答案中的问题+1不是静态分配的,堆栈分配如果是静态分配的,这很好,不是线程安全的,但是很好。它是本地分配的。@pm100:是的。更准确地说,它具有自动存储时间。谢谢Paulpro。你还回答了我在下面删除的评论@atycnth的答案中的问题+1好的,这是有道理的。但是我还是不明白为什么printf会覆盖内存?@Remi.b:函数返回后,数组就不存在了。在典型的实现中,分配给它的内存仍然存在,但它位于堆栈顶部之上。任何使用堆栈的操作都可以重新分配相同的内存并删除其值。行为是未定义的。我想编译器可以从函数中优化出一些赋值,因为如果删除printf,就没有意义给数组赋值。比较有和没有printf的汇编代码,我想会有区别。另外,尝试编译而不进行任何优化。但无论如何,这都是错误的,这是未定义的行为,试图理解它为什么会这样或那样做是没有意义的。非常感谢你的帮助+1在这种特殊情况下,我会让函数接受两个参数,double和double*,并从main以这种方式调用它:double arr[2];funcd,arr;所以你根本不考虑内存分配。好的,这是有道理的。但是我还是不明白为什么printf会覆盖内存?@Remi.b:函数返回后,数组就不存在了。在一个典型的实现中,内存t
分配给它的帽子仍然存在,但它位于堆栈顶部之上。任何使用堆栈的操作都可以重新分配相同的内存并删除其值。行为是未定义的。我想编译器可以从函数中优化出一些赋值,因为如果删除printf,就没有意义给数组赋值。比较有和没有printf的汇编代码,我想会有区别。另外,尝试编译而不进行任何优化。但无论如何,这都是错误的,这是未定义的行为,试图理解它为什么会这样或那样做是没有意义的。非常感谢你的帮助+1在这种特殊情况下,我会让函数接受两个参数,double和double*,并从main以这种方式调用它:double arr[2];funcd,arr;所以你根本不考虑内存分配。