13

我可以使用perror()strerror()打印属于 的“人类可读”错误消息errno,但如果我还想打印 的符号名称(例如“ EAGAIN”)errno怎么办?

任何方便的功能或宏来做到这一点?

更新:根据下面接受的答案及其评论的想法,附上我最终编写的代码:

#include <ctype.h>
#include <errno.h>
#include <stdio.h>

int get_errno_name(char *buf, int buf_size) {
    // Using the linux-only gawk instead of awk, because of the convenient
    // match() functionality. For Posix portability, use a different recipe...
    char cmd[] = "e=       && " // errno to be inserted here (max digits = 6)
                 "echo '#include <errno.h>' | "
                 "gcc -dM -E - | " // optionally, use $CC inead of gcc
                 "gawk \"match(\\$0, /^#[[:space:]]*define[[:space:]]+"
                     "(E[[:alnum:]]+)[[:space:]]+$e($|[^[:alnum:]])/, m) "
                     "{ print m[1] }\"";
    {
        // Insert the errno as the "e" shell variable in the command above.
        int errno_digit_c = snprintf(cmd + 2, 6, "%d", errno);
        if (errno_digit_c < 1) {
            fprintf(stderr, "Failed to stringify an errno "
                            "in get_errno_name().\n");
            return -1;
        }
        // Replace the inserted terminating '\0' with whitespace
        cmd[errno_digit_c + 2] = ' ';
    }
    FILE *f = popen(cmd, "r");
    if (f == NULL) {
        perror("Failed to popen() in get_errno_name()");
        return -1;
    }
    int read_size = 0, c;
    while ((c = getc(f)) != EOF) {
        if (isalnum(c)) {
            buf[read_size++] = c;
            if (read_size + 1 > buf_size) {
                fprintf(stderr, "Read errno name is larger than the character "
                                "buffer supplied to get_errno_name().\n");
                return -1;
            }
        }
    }
    buf[read_size++] = '\0';
    if (pclose(f) == -1) {
        perror("Failed to pclose() in get_errno_name()");
        return -1;
    }
    return read_size;
}
4

7 回答 7

6

我最近编写了一个errnoname,它有一个errnoname可以让你做到这一点的函数。

不幸的是,仍然没有标准的 API 可以做到这一点。

我的目标是成为您可以在任何系统上便携使用的东西,同时仍然覆盖errno该系统上的所有名称。到目前为止,包括 Linux、Darwin(macOS、iOS 等)、FreeBSD、NetBSD、OpenBSD、DragonflyBSD、几个闭源 Unix、Windows 和其他一些。

正如其他答案所示,唯一的“困难”部分是获取errno名称和值的列表以进行查找,知道甚至在目标系统上定义了哪些,并详尽地处理多个名称可能映射到同一数字的errno所有情况。errno

所以在errnoname图书馆你不必处理任何这些。errno我将许多操作系统的名称作为单独的步骤收集到一个列表中,然后从中生成实际发布的 C 代码。C 代码#ifdef用于每个名称,因此它可以在任何系统上编译,而不管errno系统具有哪些名称和值。编译后的结果只是简单高效的代码,无需调用任何程序或errno在库头中搜索。

无论如何,由于它是在“零条款 BSD 许可证”(0BSD)下发布的,这是一个许可许可证,或者更准确地说是一个等效于公共领域的许可证,你可以用它做任何你想做的事情。

下面是我的库中函数的旧复制粘贴,因此即使我的 repo 链接失效,这个答案也很有用。几点注意事项:

  1. 此处的副本仅涵盖截至 2019 年 8 月开始时errno我能找到的所有名字——从那时起我找到了其他人。

  2. 如果你给它一个不知道名字的值,它会返回一个NULL指针。errno

  3. 我将不断更新库以包含errno我找到的名称以及系统添加它们,添加其他改进,并添加重复保护,因为可能发现重复。但我不会(最后我检查过,由于答案的大小限制,不能)更新这个答案的副本。

#include <errno.h>

char const * errnoname(int errno_)
{
    switch(errno_)
    {
#ifdef E2BIG
        case E2BIG: return "E2BIG";
#endif
#ifdef EACCES
        case EACCES: return "EACCES";
#endif
#ifdef EADDRINUSE
        case EADDRINUSE: return "EADDRINUSE";
#endif
#ifdef EADDRNOTAVAIL
        case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
#endif
#ifdef EADI
        case EADI: return "EADI";
#endif
#ifdef EADV
        case EADV: return "EADV";
#endif
#ifdef EAFNOSUPPORT
        case EAFNOSUPPORT: return "EAFNOSUPPORT";
#endif
#ifdef EAGAIN
        case EAGAIN: return "EAGAIN";
#endif
#ifdef EAIO
        case EAIO: return "EAIO";
#endif
#ifdef EALIGN
        case EALIGN: return "EALIGN";
#endif
#ifdef EALREADY
        case EALREADY: return "EALREADY";
#endif
#ifdef EASYNC
        case EASYNC: return "EASYNC";
#endif
#ifdef EAUTH
        case EAUTH: return "EAUTH";
#endif
#ifdef EBADARCH
        case EBADARCH: return "EBADARCH";
#endif
#ifdef EBADE
        case EBADE: return "EBADE";
#endif
#ifdef EBADEXEC
        case EBADEXEC: return "EBADEXEC";
#endif
#ifdef EBADF
        case EBADF: return "EBADF";
#endif
#ifdef EBADFD
        case EBADFD: return "EBADFD";
#endif
#ifdef EBADMACHO
        case EBADMACHO: return "EBADMACHO";
#endif
#ifdef EBADMSG
        case EBADMSG: return "EBADMSG";
#endif
#ifdef EBADR
        case EBADR: return "EBADR";
#endif
#ifdef EBADRPC
        case EBADRPC: return "EBADRPC";
#endif
#ifdef EBADRQC
        case EBADRQC: return "EBADRQC";
#endif
#ifdef EBADSLT
        case EBADSLT: return "EBADSLT";
#endif
#ifdef EBADVER
        case EBADVER: return "EBADVER";
#endif
#ifdef EBFONT
        case EBFONT: return "EBFONT";
#endif
#ifdef EBUSY
        case EBUSY: return "EBUSY";
#endif
#ifdef ECANCELED
        case ECANCELED: return "ECANCELED";
#endif
#if defined(ECANCELLED) && (!defined(ECANCELED) || ECANCELLED != ECANCELED)
        case ECANCELLED: return "ECANCELLED";
#endif
#ifdef ECAPMODE
        case ECAPMODE: return "ECAPMODE";
#endif
#ifdef ECHILD
        case ECHILD: return "ECHILD";
#endif
#ifdef ECHRNG
        case ECHRNG: return "ECHRNG";
#endif
#ifdef ECKPT
        case ECKPT: return "ECKPT";
#endif
#ifdef ECLONEME
        case ECLONEME: return "ECLONEME";
#endif
#ifdef ECOMM
        case ECOMM: return "ECOMM";
#endif
#ifdef ECONFIG
        case ECONFIG: return "ECONFIG";
#endif
#ifdef ECONNABORTED
        case ECONNABORTED: return "ECONNABORTED";
#endif
#ifdef ECONNREFUSED
        case ECONNREFUSED: return "ECONNREFUSED";
#endif
#ifdef ECONNRESET
        case ECONNRESET: return "ECONNRESET";
#endif
#ifdef ECORRUPT
        case ECORRUPT: return "ECORRUPT";
#endif
#ifdef ECVCERORR
        case ECVCERORR: return "ECVCERORR";
#endif
#ifdef ECVPERORR
        case ECVPERORR: return "ECVPERORR";
#endif
#ifdef EDEADLK
        case EDEADLK: return "EDEADLK";
#endif
#if defined(EDEADLOCK) && (!defined(EDEADLK) || EDEADLOCK != EDEADLK)
        case EDEADLOCK: return "EDEADLOCK";
#endif
#ifdef EDESTADDREQ
        case EDESTADDREQ: return "EDESTADDREQ";
#endif
#ifdef EDESTADDRREQ
        case EDESTADDRREQ: return "EDESTADDRREQ";
#endif
#ifdef EDEVERR
        case EDEVERR: return "EDEVERR";
#endif
#ifdef EDIRIOCTL
        case EDIRIOCTL: return "EDIRIOCTL";
#endif
#ifdef EDIRTY
        case EDIRTY: return "EDIRTY";
#endif
#ifdef EDIST
        case EDIST: return "EDIST";
#endif
#ifdef EDOM
        case EDOM: return "EDOM";
#endif
#ifdef EDOOFUS
        case EDOOFUS: return "EDOOFUS";
#endif
#ifdef EDOTDOT
        case EDOTDOT: return "EDOTDOT";
#endif
#ifdef EDQUOT
        case EDQUOT: return "EDQUOT";
#endif
#ifdef EDUPFD
        case EDUPFD: return "EDUPFD";
#endif
#ifdef EDUPPKG
        case EDUPPKG: return "EDUPPKG";
#endif
#ifdef EEXIST
        case EEXIST: return "EEXIST";
#endif
#ifdef EFAIL
        case EFAIL: return "EFAIL";
#endif
#ifdef EFAULT
        case EFAULT: return "EFAULT";
#endif
#ifdef EFBIG
        case EFBIG: return "EFBIG";
#endif
#ifdef EFORMAT
        case EFORMAT: return "EFORMAT";
#endif
#ifdef EFSCORRUPTED
        case EFSCORRUPTED: return "EFSCORRUPTED";
#endif
#ifdef EFTYPE
        case EFTYPE: return "EFTYPE";
#endif
#ifdef EHOSTDOWN
        case EHOSTDOWN: return "EHOSTDOWN";
#endif
#ifdef EHOSTUNREACH
        case EHOSTUNREACH: return "EHOSTUNREACH";
#endif
#ifdef EHWPOISON
        case EHWPOISON: return "EHWPOISON";
#endif
#ifdef EIDRM
        case EIDRM: return "EIDRM";
#endif
#ifdef EILSEQ
        case EILSEQ: return "EILSEQ";
#endif
#ifdef EINIT
        case EINIT: return "EINIT";
#endif
#ifdef EINPROG
        case EINPROG: return "EINPROG";
#endif
#ifdef EINPROGRESS
        case EINPROGRESS: return "EINPROGRESS";
#endif
#ifdef EINTEGRITY
        case EINTEGRITY: return "EINTEGRITY";
#endif
#ifdef EINTR
        case EINTR: return "EINTR";
#endif
#ifdef EINVAL
        case EINVAL: return "EINVAL";
#endif
#ifdef EIO
        case EIO: return "EIO";
#endif
#ifdef EIPSEC
        case EIPSEC: return "EIPSEC";
#endif
#ifdef EISCONN
        case EISCONN: return "EISCONN";
#endif
#ifdef EISDIR
        case EISDIR: return "EISDIR";
#endif
#ifdef EISNAM
        case EISNAM: return "EISNAM";
#endif
#ifdef EJUSTRETURN
        case EJUSTRETURN: return "EJUSTRETURN";
#endif
#ifdef EKEEPLOOKING
        case EKEEPLOOKING: return "EKEEPLOOKING";
#endif
#ifdef EKEYEXPIRED
        case EKEYEXPIRED: return "EKEYEXPIRED";
#endif
#ifdef EKEYREJECTED
        case EKEYREJECTED: return "EKEYREJECTED";
#endif
#ifdef EKEYREVOKED
        case EKEYREVOKED: return "EKEYREVOKED";
#endif
#ifdef EL2HLT
        case EL2HLT: return "EL2HLT";
#endif
#ifdef EL2NSYNC
        case EL2NSYNC: return "EL2NSYNC";
#endif
#ifdef EL3HLT
        case EL3HLT: return "EL3HLT";
#endif
#ifdef EL3RST
        case EL3RST: return "EL3RST";
#endif
#ifdef ELIBACC
        case ELIBACC: return "ELIBACC";
#endif
#ifdef ELIBBAD
        case ELIBBAD: return "ELIBBAD";
#endif
#ifdef ELIBEXEC
        case ELIBEXEC: return "ELIBEXEC";
#endif
#ifdef ELIBMAX
        case ELIBMAX: return "ELIBMAX";
#endif
#ifdef ELIBSCN
        case ELIBSCN: return "ELIBSCN";
#endif
#ifdef ELNRNG
        case ELNRNG: return "ELNRNG";
#endif
#ifdef ELOCKUNMAPPED
        case ELOCKUNMAPPED: return "ELOCKUNMAPPED";
#endif
#ifdef ELOOP
        case ELOOP: return "ELOOP";
#endif
#ifdef EMEDIA
        case EMEDIA: return "EMEDIA";
#endif
#ifdef EMEDIUMTYPE
        case EMEDIUMTYPE: return "EMEDIUMTYPE";
#endif
#ifdef EMFILE
        case EMFILE: return "EMFILE";
#endif
#ifdef EMLINK
        case EMLINK: return "EMLINK";
#endif
#ifdef EMOUNTEXIT
        case EMOUNTEXIT: return "EMOUNTEXIT";
#endif
#ifdef EMOVEFD
        case EMOVEFD: return "EMOVEFD";
#endif
#ifdef EMSGSIZE
        case EMSGSIZE: return "EMSGSIZE";
#endif
#ifdef EMTIMERS
        case EMTIMERS: return "EMTIMERS";
#endif
#ifdef EMULTIHOP
        case EMULTIHOP: return "EMULTIHOP";
#endif
#ifdef ENAMETOOLONG
        case ENAMETOOLONG: return "ENAMETOOLONG";
#endif
#ifdef ENAVAIL
        case ENAVAIL: return "ENAVAIL";
#endif
#ifdef ENEEDAUTH
        case ENEEDAUTH: return "ENEEDAUTH";
#endif
#ifdef ENETDOWN
        case ENETDOWN: return "ENETDOWN";
#endif
#ifdef ENETRESET
        case ENETRESET: return "ENETRESET";
#endif
#ifdef ENETUNREACH
        case ENETUNREACH: return "ENETUNREACH";
#endif
#ifdef ENFILE
        case ENFILE: return "ENFILE";
#endif
#ifdef ENFSREMOTE
        case ENFSREMOTE: return "ENFSREMOTE";
#endif
#ifdef ENOANO
        case ENOANO: return "ENOANO";
#endif
#ifdef ENOATTR
        case ENOATTR: return "ENOATTR";
#endif
#ifdef ENOBUFS
        case ENOBUFS: return "ENOBUFS";
#endif
#ifdef ENOCONNECT
        case ENOCONNECT: return "ENOCONNECT";
#endif
#ifdef ENOCSI
        case ENOCSI: return "ENOCSI";
#endif
#ifdef ENODATA
        case ENODATA: return "ENODATA";
#endif
#ifdef ENODEV
        case ENODEV: return "ENODEV";
#endif
#ifdef ENOENT
        case ENOENT: return "ENOENT";
#endif
#ifdef ENOEXEC
        case ENOEXEC: return "ENOEXEC";
#endif
#ifdef ENOIOCTL
        case ENOIOCTL: return "ENOIOCTL";
#endif
#ifdef ENOKEY
        case ENOKEY: return "ENOKEY";
#endif
#ifdef ENOLCK
        case ENOLCK: return "ENOLCK";
#endif
#ifdef ENOLINK
        case ENOLINK: return "ENOLINK";
#endif
#ifdef ENOLOAD
        case ENOLOAD: return "ENOLOAD";
#endif
#ifdef ENOMATCH
        case ENOMATCH: return "ENOMATCH";
#endif
#ifdef ENOMEDIUM
        case ENOMEDIUM: return "ENOMEDIUM";
#endif
#ifdef ENOMEM
        case ENOMEM: return "ENOMEM";
#endif
#ifdef ENOMSG
        case ENOMSG: return "ENOMSG";
#endif
#ifdef ENONET
        case ENONET: return "ENONET";
#endif
#ifdef ENOPKG
        case ENOPKG: return "ENOPKG";
#endif
#ifdef ENOPOLICY
        case ENOPOLICY: return "ENOPOLICY";
#endif
#ifdef ENOPROTOOPT
        case ENOPROTOOPT: return "ENOPROTOOPT";
#endif
#ifdef ENOREG
        case ENOREG: return "ENOREG";
#endif
#ifdef ENOSPC
        case ENOSPC: return "ENOSPC";
#endif
#ifdef ENOSR
        case ENOSR: return "ENOSR";
#endif
#ifdef ENOSTR
        case ENOSTR: return "ENOSTR";
#endif
#ifdef ENOSYM
        case ENOSYM: return "ENOSYM";
#endif
#ifdef ENOSYS
        case ENOSYS: return "ENOSYS";
#endif
#ifdef ENOTACTIVE
        case ENOTACTIVE: return "ENOTACTIVE";
#endif
#ifdef ENOTBLK
        case ENOTBLK: return "ENOTBLK";
#endif
#ifdef ENOTCAPABLE
        case ENOTCAPABLE: return "ENOTCAPABLE";
#endif
#ifdef ENOTCONN
        case ENOTCONN: return "ENOTCONN";
#endif
#ifdef ENOTDIR
        case ENOTDIR: return "ENOTDIR";
#endif
#ifdef ENOTEMPTY
        case ENOTEMPTY: return "ENOTEMPTY";
#endif
#ifdef ENOTNAM
        case ENOTNAM: return "ENOTNAM";
#endif
#ifdef ENOTREADY
        case ENOTREADY: return "ENOTREADY";
#endif
#ifdef ENOTRECOVERABLE
        case ENOTRECOVERABLE: return "ENOTRECOVERABLE";
#endif
#ifdef ENOTRUST
        case ENOTRUST: return "ENOTRUST";
#endif
#ifdef ENOTSOCK
        case ENOTSOCK: return "ENOTSOCK";
#endif
#ifdef ENOTSUP
        case ENOTSUP: return "ENOTSUP";
#endif
#ifdef ENOTTY
        case ENOTTY: return "ENOTTY";
#endif
#ifdef ENOTUNIQ
        case ENOTUNIQ: return "ENOTUNIQ";
#endif
#ifdef ENOUNLD
        case ENOUNLD: return "ENOUNLD";
#endif
#ifdef ENOUNREG
        case ENOUNREG: return "ENOUNREG";
#endif
#ifdef ENXIO
        case ENXIO: return "ENXIO";
#endif
#ifdef EOPCOMPLETE
        case EOPCOMPLETE: return "EOPCOMPLETE";
#endif
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || EOPNOTSUPP != ENOTSUP)
        case EOPNOTSUPP: return "EOPNOTSUPP";
#endif
#ifdef EOVERFLOW
        case EOVERFLOW: return "EOVERFLOW";
#endif
#ifdef EOWNERDEAD
        case EOWNERDEAD: return "EOWNERDEAD";
#endif
#ifdef EPASSTHROUGH
        case EPASSTHROUGH: return "EPASSTHROUGH";
#endif
#ifdef EPATHREMOTE
        case EPATHREMOTE: return "EPATHREMOTE";
#endif
#ifdef EPERM
        case EPERM: return "EPERM";
#endif
#ifdef EPFNOSUPPORT
        case EPFNOSUPPORT: return "EPFNOSUPPORT";
#endif
#ifdef EPIPE
        case EPIPE: return "EPIPE";
#endif
#ifdef EPOWERF
        case EPOWERF: return "EPOWERF";
#endif
#ifdef EPROCLIM
        case EPROCLIM: return "EPROCLIM";
#endif
#ifdef EPROCUNAVAIL
        case EPROCUNAVAIL: return "EPROCUNAVAIL";
#endif
#ifdef EPROGMISMATCH
        case EPROGMISMATCH: return "EPROGMISMATCH";
#endif
#ifdef EPROGUNAVAIL
        case EPROGUNAVAIL: return "EPROGUNAVAIL";
#endif
#ifdef EPROTO
        case EPROTO: return "EPROTO";
#endif
#ifdef EPROTONOSUPPORT
        case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
#endif
#ifdef EPROTOTYPE
        case EPROTOTYPE: return "EPROTOTYPE";
#endif
#ifdef EPWROFF
        case EPWROFF: return "EPWROFF";
#endif
#ifdef EQFULL
        case EQFULL: return "EQFULL";
#endif
#ifdef EQSUSPENDED
        case EQSUSPENDED: return "EQSUSPENDED";
#endif
#ifdef ERANGE
        case ERANGE: return "ERANGE";
#endif
#ifdef ERECYCLE
        case ERECYCLE: return "ERECYCLE";
#endif
#ifdef EREDRIVEOPEN
        case EREDRIVEOPEN: return "EREDRIVEOPEN";
#endif
#ifdef EREFUSED
        case EREFUSED: return "EREFUSED";
#endif
#ifdef ERELOC
        case ERELOC: return "ERELOC";
#endif
#ifdef ERELOCATED
        case ERELOCATED: return "ERELOCATED";
#endif
#ifdef ERELOOKUP
        case ERELOOKUP: return "ERELOOKUP";
#endif
#ifdef EREMCHG
        case EREMCHG: return "EREMCHG";
#endif
#ifdef EREMDEV
        case EREMDEV: return "EREMDEV";
#endif
#ifdef EREMOTE
        case EREMOTE: return "EREMOTE";
#endif
#ifdef EREMOTEIO
        case EREMOTEIO: return "EREMOTEIO";
#endif
#ifdef EREMOTERELEASE
        case EREMOTERELEASE: return "EREMOTERELEASE";
#endif
#ifdef ERESTART
        case ERESTART: return "ERESTART";
#endif
#ifdef ERFKILL
        case ERFKILL: return "ERFKILL";
#endif
#ifdef EROFS
        case EROFS: return "EROFS";
#endif
#ifdef ERPCMISMATCH
        case ERPCMISMATCH: return "ERPCMISMATCH";
#endif
#ifdef ESAD
        case ESAD: return "ESAD";
#endif
#ifdef ESHLIBVERS
        case ESHLIBVERS: return "ESHLIBVERS";
#endif
#ifdef ESHUTDOWN
        case ESHUTDOWN: return "ESHUTDOWN";
#endif
#ifdef ESOCKTNOSUPPORT
        case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
#endif
#ifdef ESOFT
        case ESOFT: return "ESOFT";
#endif
#ifdef ESPIPE
        case ESPIPE: return "ESPIPE";
#endif
#ifdef ESRCH
        case ESRCH: return "ESRCH";
#endif
#ifdef ESRMNT
        case ESRMNT: return "ESRMNT";
#endif
#ifdef ESTALE
        case ESTALE: return "ESTALE";
#endif
#ifdef ESTART
        case ESTART: return "ESTART";
#endif
#ifdef ESTRPIPE
        case ESTRPIPE: return "ESTRPIPE";
#endif
#ifdef ESYSERROR
        case ESYSERROR: return "ESYSERROR";
#endif
#ifdef ETIME
        case ETIME: return "ETIME";
#endif
#ifdef ETIMEDOUT
        case ETIMEDOUT: return "ETIMEDOUT";
#endif
#ifdef ETOOMANYREFS
        case ETOOMANYREFS: return "ETOOMANYREFS";
#endif
#ifdef ETXTBSY
        case ETXTBSY: return "ETXTBSY";
#endif
#ifdef EUCLEAN
        case EUCLEAN: return "EUCLEAN";
#endif
#ifdef EUNATCH
        case EUNATCH: return "EUNATCH";
#endif
#ifdef EUSERS
        case EUSERS: return "EUSERS";
#endif
#ifdef EVERSION
        case EVERSION: return "EVERSION";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EWOULDBLOCK != EAGAIN)
        case EWOULDBLOCK: return "EWOULDBLOCK";
#endif
#ifdef EWRONGFS
        case EWRONGFS: return "EWRONGFS";
#endif
#ifdef EWRPROTECT
        case EWRPROTECT: return "EWRPROTECT";
#endif
#ifdef EXDEV
        case EXDEV: return "EXDEV";
#endif
#ifdef EXFULL
        case EXFULL: return "EXFULL";
#endif
    }
    return 0;
}
于 2019-08-16T05:20:41.090 回答
4

没有简单的方法可以做到这一点。

你可以创建一个程序——我已经创建了一个,它可以重新打包为一个库函数——从数字转换为名称。但是生成表格比较困难。我使用 Perl 脚本运行带有选项 () 的编译器(GCC 或等效项)-H来列出 include 包含的标头,/usr/include/errno.h然后扫描这些文件,查找名称(#define加上E后跟大写字母或数字),数字和评论。这适用于 Linux、Mac OS X、Solaris、HP-UX、AIX。这不是特别琐碎。

请注意,errno.hMac OS X 上的 包含一个名称ELAST(为实现使用而保留的名称),它是最高数字的副本(但映射因版本而异;我相信它在 Mountain Lion 中是 105,但它在小牛队是 106)。

于 2013-11-10T02:05:27.670 回答
3

glibc 为此提供了一个函数(一个 GNU 扩展):strerrorname_np().

它在<string.h>.

它返回errno有效值或NULL无效值的名称。

man strerrorname_np

它是在 glibc 2.32 中添加的。

于 2021-02-17T07:12:21.410 回答
2

据我所知,你不能。无论如何,一些整数错误常量映射到多个符号名称,例如 EAGAIN 和 EWOULDBLOCK。显然,您可以在设置 errno 的命令的手册页上查找它们。

于 2013-11-10T01:52:43.687 回答
1

如果你知道你期待什么错误,你可以用下面的风格写 bigswitch/caseif/elseblocks against errno

if (errno == EAGAIN)
    fprintf(stderr, "EAGAIN");

这样做的明显问题是,如果您想要特定的 errno 'name',则需要针对每个可能的选项进行编写,并且有很多选项。

于 2013-11-10T02:00:25.600 回答
0

我不知道有什么函数可以做到这一点,但是如果您熟悉程序中返回的错误,那么编写一个函数并不难。

您可以编写包含 strerror() 输出的字符串,并使用 for 循环和带有 strcmp() 的 if 语句(根据成功或失败返回一个值)来比较您编写的字符串。如果它们相同,则可以输出符号名称*(如果将其设置为另一个字符串)。

于 2013-11-10T01:56:24.563 回答
0

由于符号名称存储为枚举并将C它们视为Ints. 您将必须创建一个类似于此 SO 问题How to convert enum names to string in c的函数。您可能很容易将其缩短为宏,但必须为每个错误创建一个案例。

于 2013-11-10T02:00:37.720 回答