问题
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 #include
d; 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