C语言 是否需要包括< errno.h>使用perror?

jgovgodb  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(85)

我可以使用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>是非标准的吗?

isr3a4wc

isr3a4wc1#

是的,允许使用perror而不包括errno.h。C standard的第7.21.10.4p1节给出了此函数的以下概要:

#include <stdio.h>
void perror(const char *s);

字符串
只有在访问errno宏时才需要包含errno.h。

ipakzgxi

ipakzgxi2#

是否使用perror而不包括<errno.h>标准?
是的
我想你是指直接打电话

perror("context label");

字符串
......因为其他方法,例如通过外部提供的函数指针调用函数,甚至更没有理由需要任何头。
函数调用表达式的(唯一)形式约束是:
表示被调用函数的表达式应具有指向返回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()(您不应该这样做),那么#includstdio.h进行编译就足以得到它声明。
这就是你所需要的所有头文件。perror()函数不是由你调用它的编译单元实现的,所以它在调用时没有可见性,也不受任何声明的影响,除非已经讨论过。特别是,errno变量本身就存在,并且有静态存储持续时间和外部链接。无论您的任何转换单元是否包含errno.h。您不需要包含errno.h,标准库函数就可以设置或读取该变量。
该规范的6.5.2.2部分也给出了一些关于函数调用的其他语义规则,但没有一个规则涉及头包含。

相关问题