简体   繁体   English

Printf似乎弄乱了一个简单的C程序的输出

[英]Printf seems to mess the output of a simple C program

I have some code to add fractions. 我有一些代码来添加分数。

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

struct frac
{
    int enumerator;
    int denominator;
};
typedef struct frac frac_t;


frac_t *Add(frac_t *b1, frac_t *b2)
{
  frac_t rfrac;
  frac_t *p;
  p = &rfrac;
 (*p).enumerator= ((*b1).enumerator* (*b2).denominator) + ((*b2).enumerator* (*b1).denominator);
 (*p).denominator= ((*b1).denominator* (*b2).denominator);
  return p;
}

int main(void)
{
  frac_t b1 = {2,4};
  frac_t b2 = {1,7};
  frac_t *add = Add(&b1, &b2);
  printf("%i %i\n", add->enumerator, add->denominator);
  system("pause");
  return 0;
}

This works perfectly fine. 这工作得很好。 The result is: 3 5, as it is supposed to be. 结果是:3 5,应该是。

If I add a "printf" it totally messes up my result: 如果我添加一个“ printf”,它将完全弄乱我的结果:

int main(void)
{
 frac_t b1 = {2,4};
 frac_t b2 = {1,7};
 frac_t *add = Add(&b1, &b2);
 printf("addition:\n"); 
 printf("%i %i\n", add->enumerator, add->denominator);
 system("pause");
 return 0;
}

The result is: 结果是:

addition: 加成:

2008958704 -1 2008958704 -1

What went wrong? 什么地方出了错?

Your function Add is returning a pointer to a temporary variable created within that function. 您的函数Add返回指向在该函数中创建的临时变量的指针。 Once that function has returned, the program can use that memory in any way it wishes; 该函数返回后,程序可以按其希望的任何方式使用该内存。 you should not be accessing it any longer. 您不应该再访问它了。 You got lucky the first time -- the program happened to leave that area of memory alone, and your result was preserved. 第一次您很幸运–该程序恰好不占用该内存区域,因此您的结果得以保留。 Adding in the second printf caused additional modifications to the stack memory, and this overwrote your original values and exposed the bug. 添加第二个printf导致对堆栈内存的其他修改,这将覆盖原始值并暴露了该错误。

You should pass a pointer to frac_t to the function Add instead to get your result. 你应该通过一个指针frac_t的功能Add ,而不是让你的结果。 Eg: 例如:

void Add(frac_t *result, frac_t *b1, frac_t *b2) {
    // modify result here
}

In

frac_t *Add(frac_t *b1, frac_t *b2)
{
  frac_t rfrac;
  frac_t *p;
  p = &rfrac;
 (*p).enumerator= ((*b1).enumerator* (*b2).denominator) + ((*b2).enumerator* (*b1).denominator);
 (*p).denominator= ((*b1).denominator* (*b2).denominator);
  return p;
}

you return the address of a local variable, rfrac. 您返回局部变量rfrac的地址。 This gives you undefined behaviour when you come to use it. 当您开始使用它时,它将给您带来不确定的行为。 The printf() call simply caused the UB to manifest itself. 调用printf()只是导致UB表现出来。

You are returning the address of an object that is local to the function Add . 您将返回函数Add本地的对象的地址。 This means that once you leave the function the address is no longer valid, the object has been destroyed. 这意味着,一旦离开函数,该地址将不再有效,则该对象已被销毁。

If you try to access the object, sometimes it might work (as in your first example), but much of the time it won't and you cannot rely on what the program might do. 如果您尝试访问该对象,有时它可能会起作用(如第一个示例中所示),但是在大多数情况下它不会起作用,并且您不能依赖程序可能会做什么。

You need to change to function either to return a struct by value and not a pointer to a local struct, or to take in a pointer to a struct to which it should write a result, or to dynamically allocate memory for the result and return a pointer to this memory. 您需要更改为函数,以按值返回结构而不是指向本地结构的指针,或者接受指向应向其写入结果的结构的指针,或者为结果动态分配内存并返回指向此内存的指针。 In the last case the caller would have to be responsible for freeing that memory. 在最后一种情况下,调用者必须负责释放该内存。

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

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