我有一个打开文件并检查其长度的程序.
FILE* fd = fopen(argv[1],"rb"); fseek(fd,SEEK_END); size_t flen = ftell(fd); if (flen == ((size_t)-1)) { printf("%s is a directory.\n",argv[1]); fclose(fd); exit(1); }
现在,至少在Linux下,fopen()在打开目录时返回一个有效的文件描述符.这导致查找操作返回-1(或者,在64位系统上,size_t是无符号的,0xFFFFFFFFFFFFFFFF = 264-1).
不幸的是,上面代码中的条件(flen ==((size_t)-1))没有捕获到这种情况,flen == 0xFFFFFFFF(编辑:应该是0xFFFFFFFFFFFFFFFF)也没有. printf() – 将%x或%d作为格式字符串的命令显示比较的两侧应具有相同的值.
为什么比较运算符表现得如此奇怪,即使双方属于同一类型(size_t)?我使用gcc 4.8.1作为编译器.
解决方法
C99标准(或C2011标准)中不存在目录.因此,根据定义,打开目录可以是特定于实现的行为,也可以是未定义的行为.
fopen(3)可能失败(给出NULL结果). fseek(3)也可能失败(通过返回-1).然后你最好检查errno(3)或使用perror(3)
记录ftell返回长,-1L失败.在64位Linux上,这是0xffffffffffffffff.
你的代码应该是
FILE* fd = fopen(argv[1],"rb"); if (!fd) { perror(argv[1]); exit(EXIT_FAILURE); }; if (fseek(fd,SEEK_END)<0) { perror("fseek"); exit(EXIT_FAILURE); }; long flen = ftell(fd); if (flen == -1L) { perror("ftell"); exit(EXIT_FAILURE); };
BTW,在带有libc-2.17和3.10.6内核的Linux / Debian / Sid / AMD64上,当argv [1]为/ tmp时,代码运行正常;令人惊讶的是,flen是LONG_MAX,即0x7fffffffffffffff
顺便说一句,在Linux上,目录是文件的特例.在文件路径上使用stat(2)(和file descriptor上的fstat,可能是从某些FILE *获得fileno(3)),以了解更多关于某个文件的元数据,包括其“类型”(通过其模式).你想要opendir(3),readdir(3)& closedir(3)对目录内容进行操作.另见inode(7).