我有以下代码:
#include <stdio.h>
char * lookLine (FILE *fichero)
{
char p[25];
fgets (p, sizeof (p), fichero);
return p;
}
int main (void) {
printf ("%s\n", lookLine (fopen ("suma.c", "r")));
return 0;
}
我得到以下输出:
#��x�
不好。我打算打印出名为“suma.c”的文件的第一行。它应该打印出以下内容:
#include <stdio.h>
尽管如此,如果我将p
字符串的内容打印到同一个lookFile
函数中,它就可以了:
#include <stdio.h>
void lookLine (FILE * fichero)
{
char p[25];
fgets (p, sizeof (p), fichero);
printf ("%s\n", p);
}
int main (void) {
lookLine (fopen ("suma.c", "r"));
return 0;
}
我现在得到的输出是正确的:
#include <stdio.h>
我的理由是这样的:通过使用fgets
我在p
数组中保存第一行“name.c”的字符串,然后返回其地址,该地址由第二个参数获取printf
中的main
函数。
但我发现只有当我将printf
函数直接用于同一个lookLine
函数时,这才有效...
拜托,有人能告诉我这里到底发生了什么吗?
答案 0 :(得分:6)
这是因为您正在从read
函数返回指向本地数组的指针。
请记住,局部变量存储在堆栈中,包括数组。当函数返回时,编译器将回收堆栈空间以供其他函数调用使用。所以你有一个指针指向另一个函数的内存。
答案 1 :(得分:2)
数组p
的生命周期以return
语句结束(技术上p
是一个局部变量,自动存储持续时间;这意味着它的生命周期结束在匹配}
)。
然后程序调用未定义的行为,因为它使用了一个不确定的值(从不再指向有效内存的指针读取)。这就是你可以在read()
中打印字符串的原因,但是从main()
打印时会出现乱码。
请注意read
是一个POSIX函数,可能会干扰您定义的函数(在严格的C89或C99模式下不是问题,但大多数编译器默认不是)。 [OP同时将该函数重命名为lookLine()
。]
答案 2 :(得分:1)
正如Joachin Pileborg正确指出的那样,当你从函数返回时,你正在尝试返回一个将被回收的堆栈变量。
相反,您可以尝试传递一个字符数组,并将其大小作为函数读取的输入。顺便说一句,如果除了在读取函数中调用fgets之外你不想做任何其他事情,那么最好在main函数中调用fgets。
如果你在读取中做了一些额外的逻辑并且你也无法传递缓冲区并且它的大小作为读取函数的输入,则可以使用malloc分配读取所需的内存并将指针返回到调用函数。但是,就个人而言,我不推荐它,因为最好确保读取的调用者负责创建和删除数组。