我可以使用perror
打印人类可读的errno版本,如下所示:
#include <errno.h>
#include <stdio.h>
int main(void) {
FILE *fp = fopen("file.txt", "r");
if (fp == NULL) {
perror("Unable to open file");
return -1;
}
fclose(fp);
return 0;
}
字符串
这也适用于我的实现:
#include <stdio.h>
int main(void) {
FILE *fp = fopen("file.txt", "r");
if (fp == NULL) {
perror("Unable to open file");
return -1;
}
fclose(fp);
return 0;
}
型
使用perror
而不包括<errno.h>
是非标准的吗?
2条答案
按热度按时间isr3a4wc1#
是的,允许使用
perror
而不包括errno.h。C standard的第7.21.10.4p1节给出了此函数的以下概要:字符串
只有在访问
errno
宏时才需要包含errno.h。ipakzgxi2#
是否使用
perror
而不包括<errno.h>
标准?是的
我想你是指直接打电话
字符串
......因为其他方法,例如通过外部提供的函数指针调用函数,甚至更没有理由需要任何头。
函数调用表达式的(唯一)形式约束是:
表示被调用函数的表达式应具有指向返回void或返回数组类型以外的完整对象类型的函数的类型指针。
参数的数目应该与参数的数目一致。每个参数都应该有一个型别,以便可以将其值指派给具有其Map参数之型别的非限定版本的对象
(C23 6.5.2.2/1-2)
在C语言中很长一段时间都没有任何隐式类型,所以对于通过函数标识符的函数调用,第一个约束要求一个标识符的作用域内声明。在C23之前,第二个约束是临时的,声明提供了一个原型,但是C23不允许不包含原型的函数类型。
然而,请注意,尽管规范要求调用函数的函数指针的类型与函数定义(6.5.2.2/7)兼容,但它并不要求从头文件中提取其声明。头文件只是一种方便,而不是一种要求。
当然,这就引出了一个问题,即哪些头文件实际上提供了
perror()
的定义?语言规范中说stdio.h
提供了(C23 7.23.10.4)。当然,这并不排除其他头文件也提供了声明,但是如果您自己没有声明perror()
(您不应该这样做),那么#includ
对stdio.h
进行编译就足以得到它声明。这就是你所需要的所有头文件。
perror()
函数不是由你调用它的编译单元实现的,所以它在调用时没有可见性,也不受任何声明的影响,除非已经讨论过。特别是,errno
变量本身就存在,并且有静态存储持续时间和外部链接。无论您的任何转换单元是否包含errno.h
。您不需要包含errno.h
,标准库函数就可以设置或读取该变量。该规范的6.5.2.2部分也给出了一些关于函数调用的其他语义规则,但没有一个规则涉及头包含。