limits.h

F

frank

I read this on the internet:

I am strongly against creating a my-headers.h that simply includes all
the standard header files, when it's clearly defined which standard
headers provide which standard symbols, such as limits.h provides
PATH_MAX.

end quote. Does PATH_MAX have to be defined in limits.h, according to
standard C? I thought it certainly must, until I didn't get a hit for
it in the dinkumware compleat reference.
 
B

Ben Bacarisse

frank said:
I read this on the internet:

I am strongly against creating a my-headers.h that simply includes all
the standard header files, when it's clearly defined which standard
headers provide which standard symbols, such as limits.h provides
PATH_MAX.

end quote. Does PATH_MAX have to be defined in limits.h, according to
standard C?
No.

I thought it certainly must, until I didn't get a hit for
it in the dinkumware compleat reference.

I'd pick the Dinkumware reference too, if I had no other source to go
by. Alternatively, look at the C standard and you'll see no PATH_MAX
there at all (stdio.h defines FILENAME_MAX but that's not the macro in
question).
 
E

Ersek, Laszlo

I read this on the internet:

I am strongly against creating a my-headers.h that simply includes all
the standard header files, when it's clearly defined which standard
headers provide which standard symbols, such as limits.h provides
PATH_MAX.

end quote. Does PATH_MAX have to be defined in limits.h, according to
standard C? I thought it certainly must, until I didn't get a hit for
it in the dinkumware compleat reference.

C99 doesn't mention PATH_MAX in

7.10 Sizes of integer types <limits.h>
->
5.2.4.2.1 Sizes of integer types <limits.h>

If you mean the Single UNIX Specification, then PATH_MAX need not be
defined. You may have to use the pathconf() function, the fpathconf()
function, or the getconf utility instead.

SUSv2:
http://www.opengroup.org/onlinepubs/007908775/xsh/limits.h.html#tag_000_007_349_002

SUSv3:
http://www.opengroup.org/onlinepubs/000095399/basedefs/limits.h.html#tag_13_24_03_02

SUSv4:
http://www.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html#tag_13_23_03_02

If you program for SUSv2: you may want to use _POSIX_PATH_MAX.

If you program for SUSv3 or SUSv4: you may want to use _POSIX_PATH_MAX,
or, if the implementation conforms not only to POSIX, but also the
Single UNIX Specification, _XOPEN_PATH_MAX.

This might be of interest:

Ulrich Drepper - Directory Reading
http://udrepper.livejournal.com/18555.html

Cheers,
lacos
 
F

frank

Richard said:
On the contrary, it *must not* be defined there, or in any other
standard header.

When a compiler is directed to look along different paths for limits.h,
it's liable to find more than one.

What I'm trying to put together is how the preprocessor deals with that
situation. Plauger says header inclusion is idempotent. Ok, fine.
Does that mean if you have the identical text in 2 versions of limits.h,
the preprocessor would end at the same state after doing its thing if it
processes either once or thrice?
 
R

robertwessel2

When a compiler is directed to look along different paths for limits.h,
it's liable to find more than one.

What I'm trying to put together is how the preprocessor deals with that
situation.  Plauger says header inclusion is idempotent.  Ok, fine.
Does that mean if you have the identical text in 2 versions of limits.h,
the preprocessor would end at the same state after doing its thing if it
processes either once or thrice?


Only the standard headers are guaranteed to be idempotent (well,
except for assert.h). You can, of course, make your own headers
idempotent as well, but that's a different issue. Also, there can
only be one copy of each standard header (assuming such a thing
physically exists), and providing an additional one with a standard
name results in undefined behavior.

So there can only be one limits.h (again, there doesn't have to
physically be a file called that), but including it more than once is
harmless.

For non-standard headers, including two headers of the same name, but
in different directories, is no different than if they had different
names - it's just the contents of the specified file that gets pasted
into your source code at that point. And whatever the effect of
pasting it in two identical - or different - copies is, is what it is.
 
K

Keith Thompson

frank said:
When a compiler is directed to look along different paths for
limits.h, it's liable to find more than one.

When you write

#include <limits.h>

in your program, the compiler must find the correct version (which
might not even be a C source file).
What I'm trying to put together is how the preprocessor deals with
that situation. Plauger says header inclusion is idempotent. Ok,
fine. Does that mean if you have the identical text in 2 versions of
limits.h, the preprocessor would end at the same state after doing its
thing if it processes either once or thrice?

If you have files named "limits.h" in two different locations,
they aren't necessarily two different "versions" of limits.h;
they may just be two different files that happen to have the same
name. If you tweak your compiler's options so it finds something
other than the usual copy of the limits.h header when you write
"#include <limits.h>", and if that other copy doesn't meet the
standard's requirements for what's contained in that header, then
your tweaking has made your compiler non-conforming. How it then
behaves is entirely outside the scope of the standard.
 
S

Seebs

If that's true (and I have no reason not to believe you), it is
impossible for any implementation to conform (simultaneously) to both
ISO 9899 and POSIX.

Yes. POSIX pollutes the namespace. As a result, if I want to write
reasonably portable code, I avoid the POSIX-reserved namespace hunks
too.

-s
 
K

Keith Thompson

Seebs said:
Yes. POSIX pollutes the namespace. As a result, if I want to write
reasonably portable code, I avoid the POSIX-reserved namespace hunks
too.

Isn't that what the _POSIX_C_SOURCE macro is for?
 
S

Seebs

Isn't that what the _POSIX_C_SOURCE macro is for?

Yeah, but my confidence that an arbitrary system will actually do that
all correctly is low, so I avoid clashing with those names unless I'm doing
it on purpose.

-s
 
F

frank

Only the standard headers are guaranteed to be idempotent (well,
except for assert.h). You can, of course, make your own headers
idempotent as well, but that's a different issue. Also, there can
only be one copy of each standard header (assuming such a thing
physically exists), and providing an additional one with a standard
name results in undefined behavior.

So there can only be one limits.h (again, there doesn't have to
physically be a file called that), but including it more than once is
harmless.

For non-standard headers, including two headers of the same name, but
in different directories, is no different than if they had different
names - it's just the contents of the specified file that gets pasted
into your source code at that point. And whatever the effect of
pasting it in two identical - or different - copies is, is what it is.

Alright, thanks robert. I guess I've been trying to reconcile some odd
things today. Let me ask this:

#include <limits.h>
#include <limits.h>
....

Does only one copy of limits.h get pasted in at the top of the program?
 
F

frank

Richard said:
William Ahern wrote:



If that's true (and I have no reason not to believe you), it is
impossible for any implementation to conform (simultaneously) to both
ISO 9899 and POSIX.

So it would seem, but the PATH_MAX on the contemporary posix side isn't just
#define PATH_MAX 512

, else this line wouldn't have failed today:
char pathName[PATH_MAX + 1];

I think this is now deprecated, and PATH_MAX is some type of subvariable
after a pathconf call, but my misapprehension here is palpable.
 
R

robertwessel2

Alright, thanks robert. I guess I've been trying to reconcile some odd
things today.  Let me ask this:

#include <limits.h>
#include <limits.h>
...

Does only one copy of limits.h get pasted in at the top of the program?


Well, if you were including something other than a standard header (or
assert.h), and not making use of non-standard extensions, you would
certainly get two copies. It's a bit more complicated for the
standard headers.

The important thing is that limits.h, and the other standard headers
(again excepting assert.h), are written/implemented in such a way that
it doesn't make any difference that you included them twice.
Basically the most common approach is to put some sort of guard that
causes the second (and subsequent) includes to do nothing. The
typical guard macros:

#ifndef _LIMITS_H_GUARD
#define _LIMITS_H_GUARD
#define INT_MAX...
...
#endif _LIMITS_H_GUARD

are a common approach. Note that this *does* include two copies of
the header, but the second is hollowed out by the guard.

Some implementations have a non-standard extension like MSVC's #pragma
once, which causes subsequent inclusions of that file to be physically
suppressed. MSVC, for example, happens to use that in its
implementation of limits.h, although that what the implementation does
inside the standard headers is up to the implementation, and may
involve all sorts of implementation specific magic. Actually the MSVC
case is more complicated - the headers are coded in such a way that if
you run then through an old version of the compiler, they'll use the
traditional guard macros instead. Some other implementation specific
mechanism for making the second include have no effect might be used
as well.

But the point is that the behavior meet the rule that "Headers ...
each may be included more than once in a given scope, with no effect
different from being included only once ... (assert.h exception)".

As a side note, mucking about in forbidden ways may break that "as if
included only once behavior." For example, if you #undef the guard
macro between the two definitions (which you're not allowed to do
since the guard macro should always be in the reserved namespace, but
will be possible to do on most implementations anyway), the second
include may well do something odd. Or it may not.

But ignoring extensions like #pragma once, and the fact that the
implementation is allowed to handle the standard headers specially (as
I mentioned before, they don't actually have to be files like other
headers, just so long as the include does what's expected), an
#include just pastes the requested header file into the source code,
each and every time you ask.

As a general comment, using header guards is pretty common, even on
headers you write yourself.

Note the other rule about the standard headers is that you may include
them in any order, and it doesn't make any difference past the last
inclusion (obviously references to things in a header have to occur
after that header is included).
 
K

Kaz Kylheku

William Ahern wrote:

POSIX has feature selection macros to enable that behavior.

But that behavior may be on by default (i.e. an implementation being
nonconforming unless requested).

If you tell the comipler to be strict ISO C, it should disable
the POSIX extensions; from that point, you can use the feature
selection macros to request the exact version of POSIX.
If that's true (and I have no reason not to believe you), it is
impossible for any implementation to conform (simultaneously) to both
ISO 9899 and POSIX.

If a POSIX feature selection macro is defined, such as _POSIX_SOURCE
then indeed some ISO C headers indeed become nonconforming.

POSIX doesn't go away if these are not defined; you can still include a
header like <fcntl.h> and use its features, just not the extensions to
<stdio.h> and others.
 
F

frank

Well, if you were including something other than a standard header (or
assert.h), and not making use of non-standard extensions, you would
certainly get two copies. It's a bit more complicated for the
standard headers.

The important thing is that limits.h, and the other standard headers
(again excepting assert.h), are written/implemented in such a way that
it doesn't make any difference that you included them twice.
Basically the most common approach is to put some sort of guard that
causes the second (and subsequent) includes to do nothing. The
typical guard macros:

#ifndef _LIMITS_H_GUARD
#define _LIMITS_H_GUARD
#define INT_MAX...
...
#endif _LIMITS_H_GUARD

are a common approach. Note that this *does* include two copies of
the header, but the second is hollowed out by the guard.

Some implementations have a non-standard extension like MSVC's #pragma
once, which causes subsequent inclusions of that file to be physically
suppressed. MSVC, for example, happens to use that in its
implementation of limits.h, although that what the implementation does
inside the standard headers is up to the implementation, and may
involve all sorts of implementation specific magic. Actually the MSVC
case is more complicated - the headers are coded in such a way that if
you run then through an old version of the compiler, they'll use the
traditional guard macros instead. Some other implementation specific
mechanism for making the second include have no effect might be used
as well.

But the point is that the behavior meet the rule that "Headers ...
each may be included more than once in a given scope, with no effect
different from being included only once ... (assert.h exception)".

As a side note, mucking about in forbidden ways may break that "as if
included only once behavior." For example, if you #undef the guard
macro between the two definitions (which you're not allowed to do
since the guard macro should always be in the reserved namespace, but
will be possible to do on most implementations anyway), the second
include may well do something odd. Or it may not.

But ignoring extensions like #pragma once, and the fact that the
implementation is allowed to handle the standard headers specially (as
I mentioned before, they don't actually have to be files like other
headers, just so long as the include does what's expected), an
#include just pastes the requested header file into the source code,
each and every time you ask.

As a general comment, using header guards is pretty common, even on
headers you write yourself.

Note the other rule about the standard headers is that you may include
them in any order, and it doesn't make any difference past the last
inclusion (obviously references to things in a header have to occur
after that header is included).

I think I understand. I remember the inclusion process from MVC4 and 6:
I used Appwizard.:)

Alright so apart from assert.h, for standard headers, order and
multiplicity *can't* make a difference.
 
E

Eric Sosman

[... concerning name space pollution ...]
However, 7.1.2p1 states:

Each library function is declared, with a type that includes a
prototype, in a header, whose contents are made available by the
#include preprocessing directive. The header declares a set of
related functions, plus any necessary types and additional macros
needed to facilitate their use. Declarations of types described
in this clause shall not include type qualifiers, unless explicitly
stated otherwise.

I don't see anything that says "... and shall not declare anything not
'needed to facilitate their use'".

So, does The Standard forbid any implementation-specific extensions to
be defined within the standard header files?

No, but see 7.1.3 for a description of the identifiers such
extensions can use. In particular, see 7.1.3p2: "No other
identifiers are reserved. [...]"

The clean-as-can-be-managed way around such conflicts is
to make the intrusive declarations conditional on "feature
selection" macros with reserved names like _POSIX_SOURCE. The
idea is that defining a reserved-name macro makes the behavior
undefined w.r.t. the C Standard (7.1.3p2 again), but that the
implementation is allowed to provide its own definitions for
situations that C doesn't define. So an implementation is free
to say "Defining _POSIX_SOURCE prior to the inclusion of thus-
and-such headers causes the following effects: ... and in all
other respects the C Standard remains in force."

When you start writing headers that accommodate not only
POSIX but all the assorted versions and variations of SUSv*,
X/Open, and so on, reconciling the sometimes conflicting
Standards becomes an intricate task indeed. See, for example
<http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/feature_tests.h>.
 
S

Seebs

So, does The Standard forbid any implementation-specific extensions to be
defined within the standard header files?

It does if they're not in the namespace reserved for implementation
extensions.

-s
 
R

Richard Bos

William Ahern said:
Well, as lacos pointed out I was wrong about PATH_MAX.
But there are other macros, like _POSIX_PATH_MAX (a minimum spoken of
above), which are required. To wit:

Yes, but _POSIX_PATH_MAX is in the implementation's namespace, so Posix
_can_ require that and still be compatible with ISO C.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top