我有一个程序来打开文件并检查其长度。
FILE* fd = fopen(argv[1], "rb"); fseek(fd, 0, 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(或者,如size_t无符号,在64位系统上为0xFFFFFFFFFFFFFFFF= 2 64 -1)。
fopen()
-1
size_t
0xFFFFFFFFFFFFFFFF
不幸的是,上面的代码(flen == ((size_t)-1))中的条件无法解决这种情况,flen == 0xFFFFFFFF(EDIT:应该是0xFFFFFFFFFFFFFFFF)也没有。printf()-将%xord %d作为格式字符串的命令显示比较的两面应具有相同的值。
flen == ((size_t)-1)
flen == 0xFFFFFFFF
printf()
%x
%d
为什么即使两边都是相同类型(size_t),比较运算符的行为也是如此奇怪?我正在使用gcc 4.8.1作为编译器。
目录在C99标准(或C2011标准)中不存在。因此,根据定义,fopen-ing目录是实现特定的行为或未定义的行为。
fopen
fopen(3)可能会失败(给出NULL结果)。fseek(3)也可能失败(返回-1)。然后您最好检查errno(3)或使用perror(3)
NULL
ftell是记录在案,以返回long,和-1L失败。在64位Linux上,这是0xffffffffffffffff。
ftell
long
-1L
0xffffffffffffffff
您的代码应改为
FILE* fd = fopen(argv[1], "rb"); if (!fd) { perror(argv[1]); exit(EXIT_FAILURE); }; if (fseek(fd, 0, SEEK_END)<0) { perror("fseek"); exit(EXIT_FAILURE); }; long flen = ftell(fd); if (flen == -1L) { perror("ftell"); exit(EXIT_FAILURE); };
顺便说一句,在具有libc-2.17和3.10.6内核的Linux / Debian / Sid / AMD64上,当argv[1]is 时,代码可以正常运行/tmp;惊喜地,flen是LONG_MAX即0x7fffffffffffffff
argv[1]
/tmp
flen
LONG_MAX
0x7fffffffffffffff
顺便说一句,在Linux上,目录是文件的特例。在文件路径上(以及在文件描述符(可能是通过some从fileno(3)获取)上)使用stat(2)来了解有关某个文件的更多元数据,包括其“类型”(通过其模式)。您希望opendir(3),readdir(3)和closedir(3)对目录内容进行操作。另请参见inode(7)。fstatFILE*
fstat
FILE*