我有一个标题stderr.h,其中包括以下内容:
#if !defined(PRINTFLIKE)
#if defined(__GNUC__)
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#else
#define PRINTFLIKE(n,m) /* If only */
#endif /* __GNUC__ */
#endif /* PRINTFLIKE */
还包含如下声明:
extern NORETURN void err_abort(const char *format, ...) PRINTFLIKE(1,2);
extern NORETURN void err_error(const char *format, ...) PRINTFLIKE(1,2);
extern NORETURN void err_error1(const char *s1);
extern NORETURN void err_error2(const char *s1, const char *s2);
extern NORETURN void err_help(const char *use_str, const char *hlp_str);
extern NORETURN void err_helplist(const char *use_str, const char * const *help_list);
extern NORETURN void err_internal(const char *function, const char *format, ...) PRINTFLIKE(2,3);
extern NORETURN void err_syserr(const char *format, ...) PRINTFLIKE(1,2);
extern NORETURN void err_syserr1(const char *s1);
extern NORETURN void err_syserr2(const char *s1, const char *s2);
extern NORETURN void err_syserror(int errnum, const char *format, ...) PRINTFLIKE(2,3);
extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...) PRINTFLIKE(4,5);
extern void err_print(int flags, int estat, const char *format, va_list args);
extern void err_printversion(const char *program, const char *verinfo);
extern void err_remark(const char *format, ...) PRINTFLIKE(1,2);
extern void err_remark1(const char *s1);
extern void err_remark2(const char *s1, const char *s2);
extern void err_report(int flags, int estat, const char *format, ...) PRINTFLIKE(3,4);
extern void err_sysrem(const char *format, ...) PRINTFLIKE(1,2);
extern void err_sysrem1(const char *s1);
extern void err_sysrem2(const char *s1, const char *s2);
extern void err_sysremark(int errnum, const char *format, ...) PRINTFLIKE(2,3);
NORETURN 是另外一段条件编译,表示这些函数一旦调用就不会返回。测试稍微复杂一些,因为标准 C (ISO/IEC 9899:2011) 有一个内置机制 — _Noreturn — 可以与支持 C11 的编译器一起使用。
#if !defined(NORETURN)
#if __STDC_VERSION__ >= 201112L
#define NORETURN _Noreturn
#elif defined(__GNUC__)
#define NORETURN __attribute__((noreturn))
#else
#define NORETURN /* If only */
#endif /* __STDC_VERSION__ || __GNUC__ */
#endif /* NORETURN */
请注意,当编译器不声称是 GCC (__GNUC__) 时,该机制如何保持不碍事。除非您愿意将自己完全绑定到 GCC,否则这些方面的保护性代码是必要的。