Topic: Defining standard macros
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Wed, 14 Nov 2001 10:20:07 GMT Raw View
Michiel Salters wrote:
>
> In article <14puut42kuncimdh43kkq1docbmtdktsem@4ax.com>, Jack Klein says...
> >
> >This is based on a question that came up in comp.lang.c++, but I am
> >not sure about the legality of this issue under the standard for
> >either language.
> >
> >Is a compiler allowed to define a standard macro in a header other
> >than the one specified by the standard?
>
> Yes, because each standard header may include any other standard header.
This thread is cross-posted to both comp.std.c and comp.std.c++. Your
statement is not true in C. It is true in C++; see 17.4.4.1p1 of the C++
standard; however, even in C++ code it only applies to the C++ headers -
it doesn't apply to the C headers that are also legal to include in C++
programs.
The logic showing that this is prohibited in C is somewhat subtle. The
relevant clauses of the C standard are the ones in 7.3.1p1, governing
reserved identifiers:
"...
--_ Each macro name in any of the following subclauses (including the
future library directions) is reserved for use as specified if any of
its associated headers is included; unless explicitly stated otherwise
(see 7.1.4).
...
--_ Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is reserved for use
as a macro name and as an identifier with file scope in the same name
space if any of its associated headers is included."
Since those identifiers are reserved ONLY if the relevant headers are
#included, they cannot be defined in any of the other headers, directly
or by #inclusion. Otherwise, code that used those identifiers in a
non-reserved fashion would break.
For instance, imagine that <math.h> #includes <float.h>. Then the
following perfectly legal code would break:
#include <math.h>
// DBL_MAX is not reserved, since <float.h> has NOT been #included.
double DBL_MAX(const char *p) { return nan(p);}
Granted, that code represents extremely bad coding practice, but it is
legal.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: fred@genesis.demon.co.uk (Lawrence Kirby)
Date: Wed, 14 Nov 2001 18:22:11 GMT Raw View
In article <LK3I7.22738$xS6.35377@www.newsranger.com>
Michiel.Salters@cmg.nl "Michiel Salter" writes:
>In article <14puut42kuncimdh43kkq1docbmtdktsem@4ax.com>, Jack Klein says...
>>
>>This is based on a question that came up in comp.lang.c++, but I am
>>not sure about the legality of this issue under the standard for
>>either language.
>>
>>Is a compiler allowed to define a standard macro in a header other
>>than the one specified by the standard?
>
>Yes, because each standard header may include any other standard header.
The C standard gives no such permission.
>In general, if a.h should define X, it can also include b.h which actually
>defines X. The users of b.h can't determine whether b.h defined X or included
>a.h and got X as a side effect.
If a.h unconditionally defines X and b.h is not permitted to define X then
b.h cannot include a.h.
>Another way of looking at it is that all
>standard headers could be implemented as "#include <stdall.h>" which
>would be the union of std headers.
This is not true in C, I'd be surprised if it is true in C++. Standard C
headers have a set of identifiers that they must define in the appropriate
way. There are also reserved sets of identifiers, some related to particular
headers. A standard header can define identifiers that are generally
reserved or which are reseved when that particular header is included. It
cannot define other identifiers.
--
-----------------------------------------
Lawrence Kirby | fred@genesis.demon.co.uk
Wilts, England | 70734.126@compuserve.com
-----------------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: bruce.wheeler@siemens.at (Bruce Wheeler)
Date: Wed, 14 Nov 2001 18:22:14 GMT Raw View
On Wed, 14 Nov 2001 10:20:07 GMT, "James Kuyper Jr." <kuyper@wizard.net>
wrote:
>Michiel Salters wrote:
>>
>> In article <14puut42kuncimdh43kkq1docbmtdktsem@4ax.com>, Jack Klein says...
>> >
>> >This is based on a question that came up in comp.lang.c++, but I am
>> >not sure about the legality of this issue under the standard for
>> >either language.
>> >
>> >Is a compiler allowed to define a standard macro in a header other
>> >than the one specified by the standard?
>>
>> Yes, because each standard header may include any other standard header.
>
>This thread is cross-posted to both comp.std.c and comp.std.c++. Your
>statement is not true in C. It is true in C++; see 17.4.4.1p1 of the C++
>standard; however, even in C++ code it only applies to the C++ headers -
>it doesn't apply to the C headers that are also legal to include in C++
>programs.
>
>The logic showing that this is prohibited in C is somewhat subtle. The
>relevant clauses of the C standard are the ones in 7.3.1p1, governing
>reserved identifiers:
>
>"...
>--_ Each macro name in any of the following subclauses (including the
>future library directions) is reserved for use as specified if any of
>its associated headers is included; unless explicitly stated otherwise
>(see 7.1.4).
>...
>--_ Each identifier with file scope listed in any of the following
>subclauses (including the future library directions) is reserved for use
>as a macro name and as an identifier with file scope in the same name
>space if any of its associated headers is included."
>
...
[snip]
As you say, the C standard states "if any of its associated headers is
included", not "if and only if any of its associated headers is
included".
>Since those identifiers are reserved ONLY if the relevant headers are
>#included, they cannot be defined in any of the other headers, directly
>or by #inclusion.
Wouldn't it be possible for an implementor to argue that it is
implementation-defined whether the 'only if' implication holds, ie, that
the above statement need not necessarily hold?
Regards,
Bruce Wheeler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: news_comp.std.c++_expires-2002-01-01@nmhq.net (Niklas Matthies)
Date: Wed, 14 Nov 2001 23:21:12 GMT Raw View
On Wed, 14 Nov 2001 18:22:14 GMT, Bruce Wheeler <bruce.wheeler@siemens.at=
> wrote:
> On Wed, 14 Nov 2001 10:20:07 GMT, "James Kuyper Jr." <kuyper@wizard.ne=
t> wrote:
> >Michiel Salters wrote:
[=B7=B7=B7]
> >"...
> >--_ Each macro name in any of the following subclauses (including the
> >future library directions) is reserved for use as specified if any of
> >its associated headers is included; unless explicitly stated otherwise
> >(see 7.1.4).
> >...
> >--_ Each identifier with file scope listed in any of the following
> >subclauses (including the future library directions) is reserved for u=
se
> >as a macro name and as an identifier with file scope in the same name
> >space if any of its associated headers is included."
> >
> ...
> [snip]
> =20
> As you say, the C standard states "if any of its associated headers is
> included", not "if and only if any of its associated headers is
> included".
> =20
> >Since those identifiers are reserved ONLY if the relevant headers are
> >#included, they cannot be defined in any of the other headers, directl=
y
> >or by #inclusion.
> =20
> Wouldn't it be possible for an implementor to argue that it is
> implementation-defined whether the 'only if' implication holds, ie, th=
at
> the above statement need not necessarily hold?
Another way to argue would be to say that "if any of its associated
headers are included" also encompasses inclusion some other standard
header that itself happens to include one of the "associated headers".
-- Niklas Matthies
--=20
You have moved your mouse. Windows must be rebooted for the
changes to take effect.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Thu, 15 Nov 2001 16:56:33 GMT Raw View
Lawrence Kirby wrote:
...
> >Another way of looking at it is that all
> >standard headers could be implemented as "#include <stdall.h>" which
> >would be the union of std headers.
>
> This is not true in C, I'd be surprised if it is true in C++.
Section 17.4.4.1p1 of the C++ standard explicitly allows any C++
standard header to #include and other C++ standard header. This
permission does not extend to the headers inherited from C.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: mycoboco@hanmail.net (Jun Woong)
Date: Thu, 15 Nov 2001 16:56:47 GMT Raw View
bruce.wheeler@siemens.at (Bruce Wheeler) wrote in message news:<3bf2619c.12965333@news.siemens.at>...
> On Wed, 14 Nov 2001 10:20:07 GMT, "James Kuyper Jr." <kuyper@wizard.net> wrote:
[...]
> >
> >"...
> >--_ Each macro name in any of the following subclauses (including the
> >future library directions) is reserved for use as specified if any of
> >its associated headers is included; unless explicitly stated otherwise
> >(see 7.1.4).
> >...
> >--_ Each identifier with file scope listed in any of the following
> >subclauses (including the future library directions) is reserved for use
> >as a macro name and as an identifier with file scope in the same name
> >space if any of its associated headers is included."
> >
> ...
> [snip]
>
> As you say, the C standard states "if any of its associated headers is
> included", not "if and only if any of its associated headers is
> included".
>
> >Since those identifiers are reserved ONLY if the relevant headers are
> >#included, they cannot be defined in any of the other headers, directly
> >or by #inclusion.
>
> Wouldn't it be possible for an implementor to argue that it is
> implementation-defined whether the 'only if' implication holds, ie, that
> the above statement need not necessarily hold?
>
An implementor of a conforming implementation can't:
- declare other identifiers than the C Standard permits to reserve and
- #include a standard header in other standard headers.
I'm not sure whether I saw these in a part of the C Standard or other
C books (in which case "everyone knows" clause :). But the first
requirement implies the second, and the first requirement can be
derived from 7.1.3p1 and 7.1.3p2 of the C Standard:
] Each header declares or defines all identifiers listed in its
] associated subclause, and optionally declares or defines identifiers
] listed in its associated future library directions subclause and
] identifiers which are always reserved either for any use or for use
] as file scope identifiers.
]
] - items, some of which are cited by James Kuyper
]
] No other identifiers are reserved.
Is this unreasonable interpretation?
If an experienced implementor which claims that his implementation
conforms to the C Standard violates any of the above requirements, I
would think it's due to complexity of the Standard, not a deficient
description of the Standard; for example, it's hard to know that a
conforming implementation can't do
#define offsetof(s,m) ((NULL)[...])
even in <stddef.h>.
--
Jun Woong (mycoboco@hanmail.net)
Dept. of Physics, Univ. of Seoul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Clive D. W. Feather" <clive@on-the-train.demon.co.uk>
Date: Thu, 15 Nov 2001 19:34:39 GMT Raw View
In article <3bf2619c.12965333@news.siemens.at>, Bruce Wheeler
<bruce.wheeler@siemens.at> writes
>As you say, the C standard states "if any of its associated headers is
>included", not "if and only if any of its associated headers is
>included".
It is a general principle of the C Standard that only those things
stated apply; if it isn't stated, it doesn't apply.
In this case, it says:
[#1] Each header declares or defines all identifiers listed
in its associated subclause, and optionally declares or
defines identifiers listed in its associated future library
directions subclause and identifiers which are always
reserved either for any use or for use as file scope
identifiers.
[...]
[#2] No other identifiers are reserved.
That's it. A header declares the things it says it declares. It might
declare various reserved names if they're reserved. NOTHING ELSE.
If the intention was that a name could be declared by any header if any
other header reserved it, then there would be no point in having stuff
reserved by only one header.
>Wouldn't it be possible for an implementor to argue that it is
>implementation-defined whether the 'only if' implication holds,
No, because the standard doesn't say so.
Any more than an implementation could say "it is implementation-defined
whether 2 + 2 is 4".
--
Clive D.W. Feather, writing for himself | Home: <clive@davros.org>
Tel: +44 20 8371 1138 (work) | Web: <http://www.davros.org>
Fax: +44 20 8371 4037 (D-fax) | Work: <clive@demon.net>
Written on my laptop; please observe the Reply-To address
======================================= MODERATOR'S COMMENT:
No C++-standard-related material in this post; please consider splitting the thread.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Andrew Koenig <ark@research.att.com>
Date: Thu, 15 Nov 2001 20:17:52 GMT Raw View
Clive> That's it. A header declares the things it says it declares. It might
Clive> declare various reserved names if they're reserved. NOTHING ELSE.
On the other hand, any C++ header is permitted to include any other
C++ header. This is a difference from C. I personally think it's
unfortunate, but it's there, and it is intentional.
--
Andrew Koenig, ark@research.att.com, http://www.research.att.com/info/ark
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Jack Klein <jackklein@spamcop.net>
Date: Tue, 13 Nov 2001 01:43:46 GMT Raw View
This is based on a question that came up in comp.lang.c++, but I am
not sure about the legality of this issue under the standard for
either language.
Is a compiler allowed to define a standard macro in a header other
than the one specified by the standard?
The particular poster had a problem with multiple definitions because
his compiler's <stdlib.h> defined the macro errno. Is this behavior
conforming?
Doing a quick file search, I noticed that compilers from Microsoft,
Borland, and also DJGPP seem to do this. MetroWerks and lcc-win32 do
not.
If it is not strictly conforming for an implementation to define errno
in any header other than <errno.h> (or <cerrno> for C++), what about a
standard header including <errno.h>?
Is it legal for an implementation's standard headers to define a
standard macro either by definition or by inclusion if the user's
program does not directly include the standard header specified?
--
Jack Klein
Home: http://JK-Technology.Com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Jun Woong<mycoboco@hanmail.net>
Date: Tue, 13 Nov 2001 19:17:52 GMT Raw View
In article <14puut42kuncimdh43kkq1docbmtdktsem@4ax.com>, Jack Klein says...
>
>This is based on a question that came up in comp.lang.c++, but I am
>not sure about the legality of this issue under the standard for
>either language.
>
>Is a compiler allowed to define a standard macro in a header other
>than the one specified by the standard?
>
>The particular poster had a problem with multiple definitions because
>his compiler's <stdlib.h> defined the macro errno. Is this behavior
>conforming?
>
>Doing a quick file search, I noticed that compilers from Microsoft,
>Borland, and also DJGPP seem to do this. MetroWerks and lcc-win32 do
>not.
>
>If it is not strictly conforming for an implementation to define errno
>in any header other than <errno.h> (or <cerrno> for C++), what about a
>standard header including <errno.h>?
>
>Is it legal for an implementation's standard headers to define a
>standard macro either by definition or by inclusion if the user's
>program does not directly include the standard header specified?
>
This problem has a possibility to make people confused, I think this
should be fixed to express the intention well.
In general, a conforming implementation can't do that.
But we need to note that errno is a reserved identifier as having the
external linkage (7.5 and footnote 143). Thus a user can't do
char *errno;
or
#define errno ...
whether <errno.h> #included or not (4th item of 7.1.3 and 7.1.3p2).
And 7.5 also reserves it as a macro name, in which case it is
reserved ONLY when <errno.h> #included. (3rd item of 7.1.3) Once
<errno.h> is #included, a user can't do
#undef errno
{
int errno; // the purpose isn't to access an actual object, but ...
because we should consider that the wording of 7.5 ("If a macro
definition is suppressed in order to access an actual object, or a
program defines an identifier with the name errno, the behavior is
undefined") is absolute; I recall a discussion with Clive. But what
about just #undefining errno?
#include <errno.h>
#undef errno
... // undefine errno, but never use it for other purpose!
I think this is legal regardless of #include <errno.h>.
A strange(?) but correct thing that a user can do with errno when
<errno.h> not #included is:
{
int errno; // Note that this has no linkage.
// I assume that the cited wording above from 7.5
// affects only when <errno.h> #included, and think
// it's correct understanding.
If an implementation defines errno as a macro in (e.g.,) <stdlib.h>,
then it would brake a s.c.program that does the second one above
without an implementation magic.
#include <stdlib.h>
This problem has a possibility to make people confused, I think this
should be fixed to express the intention well.
In general, a conforming implementation can't do that.
But we need to note that errno is a reserved identifier as having the
external linkage (7.5 and footnote 143). Thus a user can't do
char *errno;
or
#define errno ...
whether <errno.h> #included or not (4th item of 7.1.3 and 7.1.3p2).
And 7.5 also reserves it as a macro name, in which case it is
reserved ONLY when <errno.h> #included. (3rd item of 7.1.3) Once
<errno.h> is #included, a user can't do
#undef errno
{
int errno; // the purpose isn't to access an actual object, but ...
because we should consider that the wording of 7.5 ("If a macro
definition is suppressed in order to access an actual object, or a
program defines an identifier with the name errno, the behavior is
undefined") is absolute; I recall a discussion with Clive. But what
about just #undefining errno?
#include <errno.h>
#undef errno
... // undefine errno, but never use it for other purpose!
I think this is legal regardless of #include <errno.h>.
A strange(?) but correct thing that a user can do with errno when
<errno.h> not #included is:
{
int errno; // Note that this has no linkage.
// I assume that the cited wording above from 7.5
// affects only when <errno.h> #included, and think
// it's correct understanding.
If an implementation defines errno as a macro in (e.g.,) <stdlib.h>,
then it would brake a s.c.program that does the second one above
without an implementation magic.
#include <stdlib.h>
int main(void)
{
int errno = 0;
return errno;
}
Thanks.
--
Jun Woong (mycoboco@hanmail.net)
Dept. of Physics, Univ. of Seoul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Tue, 13 Nov 2001 19:21:19 GMT Raw View
In article <14puut42kuncimdh43kkq1docbmtdktsem@4ax.com>, Jack Klein says...
>
>This is based on a question that came up in comp.lang.c++, but I am
>not sure about the legality of this issue under the standard for
>either language.
>
>Is a compiler allowed to define a standard macro in a header other
>than the one specified by the standard?
Yes, because each standard header may include any other standard header.
In general, if a.h should define X, it can also include b.h which actually
defines X. The users of b.h can't determine whether b.h defined X or included
a.h and got X as a side effect. Another way of looking at it is that all
standard headers could be implemented as "#include <stdall.h>" which
would be the union of std headers.
Regards,
Michiel Salters
--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Douglas A. Gwyn" <DAGwyn@null.net>
Date: Tue, 13 Nov 2001 19:22:11 GMT Raw View
Jack Klein wrote:
> Is a compiler allowed to define a standard macro in a header other
> than the one specified by the standard?
No, although some macros are specified as being defined in
multiple standard headers. The exact rules are near the
beginning of the library section of the C standard.
> The particular poster had a problem with multiple definitions because
> his compiler's <stdlib.h> defined the macro errno. Is this behavior
> conforming?
There is no such thing as "conforming behavior". Presumably
you wonder if the *implementation* conforms to the standard.
>From the information supplied, we cannot determine that.
The usual problem with errno is that some source files have
explicitly coded a declaration:
extern int errno;
But errno does not *have* to refer to an object of type int
having external linkage, and if some (possibly conforming)
implementation took advantage of the *actual* specification
to make errno a macro that, e.g. invokes a function or a
compiler intrinsic, that could easily conflict with the
explicit declaration in the program.
> If it is not strictly conforming for an implementation to define errno
> in any header other than <errno.h> (or <cerrno> for C++), what about a
> standard header including <errno.h>?
That would define errno, nicht wahr?
> Is it legal for an implementation's standard headers to define a
> standard macro either by definition or by inclusion if the user's
> program does not directly include the standard header specified?
? The requirements of the standard are much clearer to me
than this question is.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]