我有这个功能来检查文件是否存在:
#include <stdio.h>
int main(int argc, char **argv) {
int textFileExists(const char *filename){
FILE *fp= fopen(filename,'r');
if(fp==NULL){
printf("%s %s.\n","There was an error opening ", filename);
return -1;
}
return 1;
}
textFileExists("text.txt");
return 0;
}
但是当我编译这段代码时,我收到了这个警告。
warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast
FILE *fp= fopen(filename,'r');
运行此代码会给我一个分段错误。
这里发生了什么?
答案 0 :(得分:4)
使用文字'r'
作为fopen
参数等同于使用以下内容:
const char* filename = ...;
char mode = 'r';
fopen(filename, mode);
因此假定'r'
的类型为char
,其值为0x72(ASCII)。然后将其传递给char* mode
,将0x72转换为要读取的内存地址(指针),以获得mode
字符串fopen
的字符。访问0x72的内存位置失败,因为该位置很可能无法供您的应用程序使用。
对于char*
字面值,您需要在
"r"
const char* filename = ...;
const char* mode = "r";
fopen(filename, mode);
答案 1 :(得分:3)
'r'
是一个单个字符,当传递给函数时,其类型为int
。
函数fopen()
期望第二个参数是(const
)指向char的指针(即const char *
)。因此警告信息。由于各种原因,C中允许从int
转换为指针,但编译器通常会将此类转换视为可疑,并发出警告。
该函数期望传递的指针是一个字符串,这意味着它假定该值指向char数组的第一个字符。它没有(因为你已经通过int
)所以展示未定义的行为。未定义行为的一个症状是分段违规(由操作系统检测到程序访问内存不应该导致,并向程序发送SIGSEGV
信号)。
要解决问题,请通过"r"
代替'r'
。请注意双引号而不是单引号。 "r"
是一个字符串文字,使用'r'
和'\0'
两个字符表示,这是fopen()
所期望的。执行此操作将消除运行程序时的警告和错误。
养成在运行程序之前检查编译器的警告消息的习惯。警告通常表明存在潜在问题 - 在这种情况下,警告的原因也是程序异常退出的原因。
答案 2 :(得分:-1)
在C中,'r'
和"r"
之间存在差异。检查你的C书。