繁体   English   中英

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

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

我有一些代码来添加分数。

#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;
}

这工作得很好。 结果是:3 5,应该是。

如果我添加一个“ 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;
}

结果是:

加成:

2008958704 -1

什么地方出了错?

您的函数Add返回指向在该函数中创建的临时变量的指针。 该函数返回后,程序可以按其希望的任何方式使用该内存。 您不应该再访问它了。 第一次您很幸运–该程序恰好不占用该内存区域,因此您的结果得以保留。 添加第二个printf导致对堆栈内存的其他修改,这将覆盖原始值并暴露了该错误。

你应该通过一个指针frac_t的功能Add ,而不是让你的结果。 例如:

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

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;
}

您返回局部变量rfrac的地址。 当您开始使用它时,它将给您带来不确定的行为。 调用printf()只是导致UB表现出来。

您将返回函数Add本地的对象的地址。 这意味着,一旦离开函数,该地址将不再有效,则该对象已被销毁。

如果您尝试访问该对象,有时它可能会起作用(如第一个示例中所示),但是在大多数情况下它不会起作用,并且您不能依赖程序可能会做什么。

您需要更改为函数,以按值返回结构而不是指向本地结构的指针,或者接受指向应向其写入结果的结构的指针,或者为结果动态分配内存并返回指向此内存的指针。 在最后一种情况下,调用者必须负责释放该内存。

暂无
暂无

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

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