问题
It seems that the C libraries and language has a lot of useless type names. For example, C has a built in type _Bool and there is a macro in stdbool.h, #define bool _Bool. Why didn't C just have bool built in instead of _Bool? I found more examples in stdio.h and stdlib.h. Like this:
# define WEXITSTATUS(status) __WEXITSTATUS (status)
# define WTERMSIG(status) __WTERMSIG (status)
# define WSTOPSIG(status) __WSTOPSIG (status)
# define WIFEXITED(status) __WIFEXITED (status)
# define WIFSIGNALED(status) __WIFSIGNALED (status)
# define WIFSTOPPED(status) __WIFSTOPPED (status)
# ifdef __WIFCONTINUED
# define WIFCONTINUED(status) __WIFCONTINUED (status)
# endif
My question is why bother declaring a function __FUNCTIONNAME (arg) and then #define FUNCTIONNAME(arg) __FUNCTIONNAME(arg)? Why not just declare FUNCTIONNAME(arg) to start with?
Another example in stdio.h:
extern FILE *__stdinp;
extern FILE *__stdoutp;
extern FILE *__stderrp;
And later:
#define stdin __stdinp
#define stdout __stdoutp
#define stderr __stderrp
Like seriously, why? What is wrong with just defining them then declaring them like this:
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
Why didn't they just declare the functions without the underscores and then have no need for these macros?
回答1:
It's all about namespace management.
Names prefixed with two underscores or an underscore and an upper case letter are implementation-reserved. An implementation may expose them virtually indiscriminately (well, it's not really very clear which reserved names belong to compilers and which to libc implementations).
Names like WIFCONTINUED, on the other hand, belong to the user (and <sys/wait.h> under POSIX), and stdlib.h shouldn't contain them under POSIX.
GLIBC exposes them from stdlib.h only conditionally:
#if (defined __USE_XOPEN || defined __USE_XOPEN2K8) && !defined _SYS_WAIT_H
/* XPG requires a few symbols from <sys/wait.h> being defined. */
# include <bits/waitflags.h>
# include <bits/waitstatus.h>
/* Define the macros <sys/wait.h> also would define this way. */
# define WEXITSTATUS(status) __WEXITSTATUS (status)
# define WTERMSIG(status) __WTERMSIG (status)
# define WSTOPSIG(status) __WSTOPSIG (status)
# define WIFEXITED(status) __WIFEXITED (status)
# define WIFSIGNALED(status) __WIFSIGNALED (status)
# define WIFSTOPPED(status) __WIFSTOPPED (status)
# ifdef __WIFCONTINUED
# define WIFCONTINUED(status) __WIFCONTINUED (status)
# endif
#endif /* X/Open or XPG7 and <sys/wait.h> not included. */
and it's not including them by #including <sys/wait.h> probably because <sys/wait.h> likely has other stuff that shouldn't be included even if the condition for this #if (triggered by the right feature test macros ) block is satisfied.
When they use the prefixed forms (defined in the internal <bits/waitstatus.h>), <sys/wait.h> can then reuse the same ones (identically redefined macros don't generate warnings) and everything works even when they're both #included; and no header exposes more non-reserved names than required by the standards in force (the standards in use depend on the feature test macros with which you compile).
Gtk is just wrong. Gtk isn't a libc implementation, and so it has no business using those reserved names.
来源:https://stackoverflow.com/questions/55152124/why-do-the-c-libraries-and-language-define-name-and-then-typedef-or-pound-defin