【问题标题】:Printf seems to mess the output of a simple C programPrintf 似乎弄乱了一个简单的 C 程序的输出
【发布时间】:2009-12-06 15:18:44
【问题描述】:

我有一些代码可以添加分数。

#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

出了什么问题?

【问题讨论】:

标签: c pointers structure printf


【解决方案1】:

您的函数Add 正在返回一个指向在该函数中创建的临时变量的指针。一旦该函数返回,程序就可以以任何它希望的方式使用该内存;你不应该再访问它了。第一次你很幸运——程序碰巧不理会那个内存区域,你的结果被保留了。添加第二个printf 会导致对堆栈内存的额外修改,这会覆盖您的原始值并暴露错误。

您应该将指向 frac_t 的指针传递给函数 Add 以获得结果。例如:

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

【讨论】:

    【解决方案2】:

    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 显示自身。

    【讨论】:

      【解决方案3】:

      您正在返回函数 Add 的本地对象的地址。这意味着一旦你离开函数,地址就不再有效,对象就被销毁了。

      如果您尝试访问该对象,有时它可能会起作用(如在您的第一个示例中),但很多时候它不会,您不能依赖程序可能会做什么。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-20
        • 2017-01-09
        • 2015-02-25
        相关资源
        最近更新 更多