C 库宏 - errno
描述
C 库宏 extern int errno 是通过系统调用设置的,在错误事件中的某些库函数表明了什么发生了错误。
errno
是 C 标准库中的一个宏,定义在 <errno.h>
头文件中。它用于指示在程序运行过程中发生的错误。errno
实际上是一个整数变量,用于存储错误代码。库函数在发生错误时,会设置 errno
为适当的错误代码,以便程序可以检查和处理这些错误。
声明
下面是 errno 宏的声明。
extern int errno
参数
- NA
返回值
- NA
使用 errno
的步骤
- 包含头文件:在使用
errno
之前,需要包含<errno.h>
头文件。 - 调用函数:调用可能会设置
errno
的函数。 - 检查
errno
:在函数返回表示错误时,检查errno
以获取错误类型。 - 处理错误:根据
errno
的值,采取适当的错误处理措施。
实例
下面的实例演示了 errno 宏的用法。
实例
#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;
int main ()
{
FILE *fp;
fp = fopen("file.txt", "r");
if( fp == NULL )
{
fprintf(stderr, "Value of errno: %d\n", errno);
fprintf(stderr, "Error opening file: %s\n", strerror(errno));
}
else
{
fclose(fp);
}
return(0);
}
让我们编译并运行上面的程序,当文件 file.txt 不存在时,将产生以下结果:
Value of errno: 2 Error opening file: No such file or directory
常见的 errno
值
EPERM
:操作不允许ENOENT
:没有这样的文件或目录ESRCH
:没有这样的进程EINTR
:中断的系统调用EIO
:输入/输出错误ENXIO
:没有这样的设备或地址E2BIG
:参数列表太长ENOMEM
:内存不足EACCES
:权限被拒绝EFAULT
:坏的地址EBUSY
:资源忙EEXIST
:文件已存在EXDEV
:跨设备链接ENODEV
:没有这样的设备ENOTDIR
:不是一个目录EISDIR
:是一个目录EINVAL
:无效的参数ENFILE
:系统文件表溢出EMFILE
:打开的文件过多ENOTTY
:不是终端设备ETXTBSY
:文本文件忙EFBIG
:文件过大ENOSPC
:设备上没有空间ESPIPE
:非法的寻址EROFS
:只读文件系统EMLINK
:链接过多EPIPE
:管道破裂
注意事项
- 线程安全:在多线程环境中,
errno
通常实现为线程局部存储(Thread-Local Storage, TLS),确保每个线程有独立的errno
值。 - 初始值:在函数调用成功时,
errno
通常不会被修改。因此在处理错误前,应确保errno
被设置为 0。 - 跨平台差异:不同操作系统和 C 标准库实现可能会定义额外的错误码。程序应避免依赖特定错误码的数值。
错误处理建议
- 检查返回值:在调用可能失败的函数时,始终检查其返回值。
- 设置
errno
为 0:在调用函数前,可以将errno
设定为 0,以便在函数调用后检查errno
是否被修改。 - 使用
strerror
和perror
:strerror
函数将errno
转换为可读的错误消息字符串;perror
函数打印出带有描述性错误消息的errno
值。
详细的错误处理
下面是一个更详细的示例,演示如何处理不同的 errno
值:
实例
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
switch (errno) {
case EACCES:
printf("Error: Permission denied\n");
break;
case ENOENT:
printf("Error: No such file or directory\n");
break;
default:
printf("Error opening file: %s\n", strerror(errno));
}
return 1;
}
// 文件处理代码
fclose(file);
return 0;
}
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
switch (errno) {
case EACCES:
printf("Error: Permission denied\n");
break;
case ENOENT:
printf("Error: No such file or directory\n");
break;
default:
printf("Error opening file: %s\n", strerror(errno));
}
return 1;
}
// 文件处理代码
fclose(file);
return 0;
}
在这个示例中,我们检查了具体的 errno
值并做了相应的处理。如果 errno
是 EACCES
(权限被拒绝)或 ENOENT
(没有这样的文件或目录),我们打印特定的错误消息;否则,我们打印通用的错误消息。
<errno.h>
提供了一种标准化的方式来报告和处理程序中的错误,使得错误处理代码更为一致和可维护。
Crossing7
126***1330@qq.com
大家可以修改上述代码里 errno 的值从而得出不同的错误类型,从 43 之后就一直是 Unknown error 错误类型。
Crossing7
126***1330@qq.com
duckduck
pan***20812@gmail.com
我做一个补充,上面应该是Windows环境下的输出,linux 下是(CentOS release 6.10 (Final))。
duckduck
pan***20812@gmail.com