[英]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.