我正在查看一些旧的C代码(下面列出),以便在新项目中重新使用它,我意识到我已经离开了最终的返回语句。奇特的是,例程工作得很好并且确实返回了正确的文件指针。任何人都可以向我解释为什么会这样吗?
FILE* openforwrite(char *name, int binary)
{
//broken out from main to keep it tidy and allow multiple output files.
FILE *file;
//first see if it exists
file = fopen(name,"r");
if (file)
{ // it does, delete it
fclose(file);
if(remove(name)) bail("Output file already exists and cannot be deleted.");
}
//now lets re-create and open it for writing
if (binary)
file = fopen(name, "wb");
else
file = fopen(name, "w");
//check it actually opened
if (!file)
bail("Error opening output file.");
//and pass the pointer back
return file; // <-- I had omitted this line initially but the routine still worked
}
答案 0 :(得分:3)
fopen
调用的返回值最终会将文件句柄放在通常用于返回值的寄存器中(例如eax
)。如果在函数退出之前没有更改该寄存器值,则它仍可用于调用者。例如,如果在fopen
之后和函数结束之前还有一个函数调用,那么它可能会覆盖eax
寄存器并且无法确定。正如其他人所说,这是不明确的行为。尽管如此,它最初是一个非常令人费解的情况(而且相当有趣)。
答案 1 :(得分:1)
它只是碰巧工作。编译器使用堆栈将参数传递给函数,并接收它们的返回值。它还在计算过程中将堆栈用于局部变量和临时变量。返回函数时,调用者查看堆栈中的特定位置以获取返回值。该值恰好包含文件指针值,因为这是函数计算的最后一个表达式。
在任何情况下,都不要认为这会再次以这种方式发挥作用。
它可能会因各种原因而中断,包括不同的编译器版本,不同的优化,或者只是因为编译器随机决定教你一课。
答案 2 :(得分:0)
问题是您调用了未定义的行为。它似乎可以工作,它可以崩溃,并且在缓冲区溢出的情况下,它可以删除文件。