我可以用一些帮助来理解让我困惑的事情。它涉及fopen()读取文件的位置。
以下代码(使用gcc 4.5.2编译的C语言):
#include <stdlib.h>
#include <stdio.h>
void try_fopen(FILE* f_handle, const char* f_name, const char* mode) {
f_handle = fopen(f_name, mode);
if( f_handle == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(EXIT_FAILURE);
}
}
int cnt_ones(FILE* pFile) {
int c;
int n = 0;
do {
c = fgetc (pFile);
if (c == '1') n++;
} while (c != EOF);
return n;
}
为什么将fopen放在一个函数中会产生一个Segfault:
int main (int argc, char** argv) {
FILE * pFile;
try_fopen(pFile, argv[1], "r"); // Gives a Segfault
printf ("The file contains %d ones.\n", cnt_ones(pFile) );
fclose (pFile);
return 0;
}
将它放入主体(与if一起):
int main (int argc, char** argv) {
FILE * pFile;
pFile = fopen(argv[1], "r"); // While this doesn't give a Segfault
if( pFile == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", argv[1]);
exit(EXIT_FAILURE);
}
printf ("The file contains %d sign characters.\n", cnt_ones(pFile) );
fclose (pFile);
return 0;
}
答案 0 :(得分:4)
C是按值传递的,而不是通过引用传递的,因此您需要将指针传递给pFile
,否则您不会在函数范围之外更改它:
void try_fopen(FILE** f_handle, const char* f_name, const char* mode) {
*f_handle = fopen(f_name, mode);
if( *f_handle == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(EXIT_FAILURE);
}
}
// ...
try_fopen(&pFile, argv[1], "r");
答案 1 :(得分:1)
因为指针pFile
通过值传递给函数try_open
。函数内部修改的值在main
中不可用。要解决此问题,您需要将指针的地址传递给函数,因此try_open
将接受FILE**
并将fopen
的结果分配给*pFile
。在调用此函数时,您应使用pFile
传递&pFile
的地址。
答案 2 :(得分:1)
您可以这样做:
File * fp;
try_fopen( &fp,.....); /* void try_fopen (FILE ** fp,....) */
或以下:
File * fp = try_fopen("file name"); /* FILE * try_fopen (const char * file_name,...) */
答案 3 :(得分:0)
原因很简单,当你将FILE *传递给function时,它的更新将会因为Value传递而丢失。尝试将FILE **传递给函数,它将起作用。有关代码段,请参阅Binyamin Sharet上面的答案
阅读此link
可以理解其原因或者
您可以更改函数try_open以返回FILE *作为返回值。
FILE *try_fopen(const char* f_name, const char* mode)
{
FILE *f_handle = NULL;
*f_handle = fopen(f_name, mode);
if( *f_handle == NULL )
{
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(0);
}
}
//In the main function.
FILE *pFile = try_fopen(argv[1], "r");