从C函数返回FILE指针时的奇怪行为

时间:2012-06-14 21:58:45

标签: c file-io

我正在查看一些旧的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
 }

3 个答案:

答案 0 :(得分:3)

fopen调用的返回值最终会将文件句柄放在通常用于返回值的寄存器中(例如eax)。如果在函数退出之前没有更改该寄存器值,则它仍可用于调用者。例如,如果在fopen之后和函数结束之前还有一个函数调用,那么它可能会覆盖eax寄存器并且无法确定。正如其他人所说,这是不明确的行为。尽管如此,它最初是一个非常令人费解的情况(而且相当有趣)。

答案 1 :(得分:1)

它只是碰巧工作。编译器使用堆栈将参数传递给函数,并接收它们的返回值。它还在计算过程中将堆栈用于局部变量和临时变量。返回函数时,调用者查看堆栈中的特定位置以获取返回值。该值恰好包含文件指针值,因为这是函数计算的最后一个表达式。

在任何情况下,都不要认为这会再次以这种方式发挥作用。

它可能会因各种原因而中断,包括不同的编译器版本,不同的优化,或者只是因为编译器随机决定教你一课。

答案 2 :(得分:0)

问题是您调用了未定义的行为。它似乎可以工作,它可以崩溃,并且在缓冲区溢出的情况下,它可以删除文件。