J
James Kanze
* Jeff Schwab:
[...]
errno is a global variable.
It certainly behaves like one.
And yes, errno is required to be a macro.
In C++. Curiously, both C and Posix also allow it to be an
indentifier with external linkage; until recently, Posix
actually required it to be declared:
extern int errno ;
In the first case 'errno' refers to a concept and/or bottom
level implementation of that concept.
In the second case 'errno' refers to a very limited tech
detail view that few if any find useful to know about, but the
purpose of which is to provide the first case's concept in a
way such that people don't have to worry about the details.
The name 'errno' has to behave as a direct reference to a
variable, so in C it can at most map to an expression that
dereferences the pointer result of a function call (but it can
there not map to a direct function call).
In C++ it can conceivably map directly to a function call, but
it would be rather silly to implement it differently in C++
and C.
Under Solaris, its definition depends on whether the -mt option
was given; in single threaded code, it's a global variable, in
multithreaded, it expands to (*(__errno())).
Curiously enough, I've been unable to find anything in Posix
concerning its semantics in a multithreaded environment;
typically, it resolves to a thread local variable (behind the
function call), and of course, anything else would make it
totally unusable. But I'm curious about things like &errno and
errno = 0. I can't find anything in any of the standards to the
effect that in multiple uses of errno (in the same thread), the
lvalue actually refers to the same int, although of course, if
this were not the case, the common sequence of setting errno to
zero, then calling a function and examining it wouldn't work.
(I suppose that there are some implicit requirements along these
lines, based on the fact that some standard functions set errno,
and expect you to be able to read the value they've set.)