printf函数会影响变量的生命吗?

时间:2014-08-12 15:51:12

标签: c pointers printf

这是我简单的C程序。

#include <stdio.h>
float*multiply(int, float);

main(){
   int i =3;
   float f = 3.50, *p;
   p = multiply(i, f);
   printf("%u\n", p);
   printf("%f\n", *p);
   return 0;
}

float *multiply(int ii, float ff){
   float product = ii * ff;
   printf("%f\n", product);
   printf("%u\n", &product);
   return (&product);
}

该程序提供以下输出: -

enter image description here

但是,当我评论出两个&#34; printf&#34; multiply函数中的语句,它给出以下输出: -

enter image description here

我确信我没有犯任何愚蠢的错误。我只是评论出两行。 谁能告诉我为什么会这样?这个操作系统/系统是否有问题? printf函数如何增加变量的生命周期?

6 个答案:

答案 0 :(得分:2)

您将返回基于堆栈的本地变量product的地址,这将导致未定义的行为。

此外,要打印指针的值,您应该使用%p而不是%uhttp://www.cplusplus.com/reference/cstdio/printf/

答案 1 :(得分:2)

这只是一种未定义的行为。变量的生命周期保持不变 - 它仅限于函数运行的时间。一旦该功能退出,所有投注都将关闭。调用printf会更改堆栈的状态,因此您看到的结果会有所不同。但是,在这两种情况下,结果都是未定义的,这意味着您的程序可以打印任何内容甚至崩溃。

您可以通过在valgrind中运行程序来检测此未定义的行为。

注意:打印指针的正确方法是printf("%p\n", (void*)&product);

答案 2 :(得分:1)

正如其他答案所述,通过返回product的地址变量,您的结果是未定义的。但是,如果您返回product的值,则结果已明确定义,您的程序将按预期工作:

#include <stdio.h>

float multiply(int ii, float ff){
    float product = ii * ff;
    return product;
}

int main(void){
    int i =3;
    float f = 3.50, p;
    p = multiply(i, f);
    printf("%p\n", &p);
    printf("%f\n", p);
    return 0;
}
  

0x7fff521cfac0
  10.500000

答案 3 :(得分:0)

函数中局部变量的地址取决于调用函数时执行点的堆栈状态(SP寄存器的值)。

换句话说,每次调用函数时,此地址都不一定相同。

因此,返回局部变量的地址会导致未定义的行为。


您可以观察以下程序的输出作为示例:

int func1()
{
    int var = 1;
    printf("%p\n",&var);
    return var;
}

int func2()
{
    int var = 2;
    func1();
    return var;
}

int main()
{
    func1(); // main --> func1
    func2(); // main --> func2 --> func1
    return 0;
}

正如@chux在下面的一条评论中暗示的那样,C语言标准没有规定应该如何在内存中分配变量。所以上面描述的问题是大多数编译器如何在内存中分配本地变量的结果。

答案 4 :(得分:0)

如果使用标记-Wall编译它,您将看到此警告:

test.c:19:4: warning: function returns address of local variable [-Wreturn-local-addr]

这是因为您返回product的内存地址,并将float p设置为指向该地址,但由于该函数已完成,因此使用的内存从堆栈中弹出,不再保证在那里,意味着p可以指向垃圾。

答案 5 :(得分:0)

在printf()和scanf()之后,有时你需要做fflush(stdin)或flushall()。试试那个。