standard include files

S

Stefan Ram

There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?
 
I

Ian Collins

There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

They may be reserved, but that reservation isn't enforced.
 
K

Keith Thompson

There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

N1570 7.1.3:

All identifiers with external linkage in any of the following
subclauses (including the future library directions) and errnoare
always reserved for use as identifiers with external linkage.

That covers all the functions declared in standard headers. So you can
define your own "sin" as long as it doesn't have external linkage.
 
E

Eric Sosman

There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

Reservations come in different scopes and contexts.

For example, `FILE' is not reserved if <stdio.h> is not
included: You are free to write `int FILE;' at file scope in
one module and `extern int FILE;' in another, and the two names
will both refer to the same `int' variable.

But then, you are *not* free to write `int fopen;' at file
scope in any module, with or without <stdio.h>. The name is of
a different "class," and the rules are different.

7.1.3p1 lists the different realms of "reserved" for different
kinds of names. You will note that the rules in the sub-paragraphs
are not all the same.
 
K

Kaz Kylheku

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

What if a header that you /need/ to include starts to clash with a name in your
program. Implementations should provide a way by which you can select the
precise standard conformance. E.g. what if someone needs to build a C90
program? It's simpler to have a switch for that in the implmentation than
to update the program.
 
K

Kaz Kylheku

There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

This seems backwards, in fact. The external names exist whether you include the
header or not. So it is actually safer to include the header: you want the
clash to be detected at compile time.

In some environments you can write, say, your own malloc function:

double malloc(char *) { ... }

This is not diagnosed at linkage because it's something that is allowed
as an extension (overriding malloc). The internal C library uses of malloc
go to the right one, but those of the programs and any third party libs
go to the overridden one.

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

Exactly. Some identifiers are not, like typedef names or macro names.
But anything that has linkage is reserved anyway.

Even for names that are not reserved unless a given header is included,
it's usually a bad idea to invade that space.

If a translation unit includes no standard headers at all, should it be
defining ptrdiff_t, et cetera?

There is a case to be made for hosted implementations being free to define all
the standard material even if no header is included at all.
 
K

Kaz Kylheku

That covers all the functions declared in standard headers. So you can
define your own "sin" as long as it doesn't have external linkage.

But this is not necessarily a good idea, so there is a case to be made for
having this diagnosed as if the header were included.
 
K

Kaz Kylheku

I can't speak for others, but _practicing_ is _learning_. When you include
only what's needed, you learn how the standard library is organized.

This is not knowledge, but useless trivia.

Including what is needed is done for the sake of faster compilation times,
when headers are implemented vi textual substitution (which is basically
still the "state of the art" in C today).
 
I

Ian Collins

I doubt including all the standard C headers would noticebly slow
compilation, even for small compilation units. The simple textual
substitution is a performance benefit compared to C++ or Java.

The C++ include mechanism is unfortunately still the same a C.
 
B

BGB

The C++ include mechanism is unfortunately still the same a C.

and is ultimately a large part of the relatively long compile times of C
and C++ ("gotta churn through this big pile of crap the preprocessor
brought in").

and there is no "ideal" way to fix it (precompiled header mechanisms
tend to be more of a non-standardized finicky kludge, ...).
 
M

Malcolm McLean

and there is no "ideal" way to fix it (precompiled header mechanisms
tend to be more of a non-standardized finicky kludge, ...).- Hide quoted text -
My evil MS Visual Studio insists on adding the line #include
"stdafx.h" to everything, including the standard C core logic files.
 
J

jacob navia

Le 23/02/12 01:38, Stefan Ram a écrit :
There was a discussion once about why people do not simply
include all possible standard headers, so that they do not
have to be so careful when choosing the needed ones.

Someone said that not including all possible standard
headers does reduce the possibility of standard names
defined in them colliding with user names. (Also including
future C versions, where a name might be defined by the
standard that is not defined now.)

But aren't all standard identifiers reserved anyway,
independently of whether the corresponding header is
included or not?

As I have already reported in a similar discussion, the lcc-win compiler
does just that: the <stdheaders.h> file includes all standard include
files.
 
B

BGB

My evil MS Visual Studio insists on adding the line #include
"stdafx.h" to everything, including the standard C core logic files.

yep.

nicer would be if headers could be treated as semi-independent
"modules", which would be "imported" rather than inlined.

the issue is, however, that doing this generally could lead to cases
where the semantics are not properly upheld, such as when defines in one
precompiled header should theoretically influence the behavior of
another header, ...

IIRC, GCC can make it work if one always includes the same headers in
the same order.

alternatively, one could impose on the allowed semantics (say,
disallowing interactions of defines or typedefs between separately
compiled headers).


I had before imagined a C variant/subset which would have instead
organized the compilation process differently (macro-expansion would
occur much later), but it itself imposed another similarly severe
restriction: macros were not allowed to alter the block-structuring of
the language, and also the contents of all possible ifdef/ifndef paths
needed to be syntactically valid (but did not require functions or types
to exist), likewise block structuring needed to remain consistent.
another alteration was switching to Java/C# style declaration parsing rules.

the intent was to make a version of the language better suited for
working in a VM, and avoiding implicit dependencies between source
module and header module contents WRT things like changing defines or
types (so a compiled module could be moved between targets), ...

the downside was that there was no real major point in doing so, so I
never got around to it. also, it wouldn't really be C either, but rather
a C-like language.


or such...
 
B

BGB

Because once upon a time that would kill the compiler (when it had to fit in
65536 bytes of memory. MacOSX, at least, now does provide a lot of include all
headers.

nevermind such things as "windows.h", which will (for MSVC) include IIRC
around 7MB of stuff...

the MinGW version includes considerably less (around 500kB IIRC).


it all does come at a drawback: longer compile times.

amusingly, if one is compiling code which doesn't use giant headers,
MSVC compiles fairly fast, whereas GCC consistently takes its time.

as the size of ones' codebase becomes larger (Mloc range), compile times
gradually become a bit more relevant (coupled with the need to rebuild
whenever changing something). (yes, make also takes its time walking the
source tree to determine what all it doesn't need to rebuild...).

this is also a partial reason for having a lot of stuff defined in data
files and using a scripting language for some things: reducing how often
one needs to rebuild.


or such...
 
Q

Quentin Pope

Le 23/02/12 01:38, Stefan Ram a écrit :
As I have already reported in a similar discussion, the lcc-win compiler
does just that: the <stdheaders.h> file includes all standard include
files.

Sorry, but this is a terrible idea.

Lazy people will use this and then send their source code to someone with
a slow CPU or not much RAM... at best inconvenience, or maybe the compile
fails needlessly because of a lack of memory.

Or people will use this in files that end up as modules in large
projects, where compile time is measured in hours: then reading in all
this useless crap will be a significant drain.

The Standard manages headers very sensibly in my opinion.

//QP
 
W

Willem

Quentin Pope wrote:
) Sorry, but this is a terrible idea.
)
) Lazy people will use this and then send their source code to someone with
) a slow CPU or not much RAM... at best inconvenience, or maybe the compile
) fails needlessly because of a lack of memory.
)
) Or people will use this in files that end up as modules in large
) projects, where compile time is measured in hours: then reading in all
) this useless crap will be a significant drain.
)
) The Standard manages headers very sensibly in my opinion.

OK, so what we need is a compiler that pre-includes all the standard
headers (AFAIK, not including a header is UB, so the compiler is allowed
to do this) and, with a special tool, inserts the list of headers that is
actually needed for when you distribute the source.

So lazy coders can start off with not including any of the headers, and
then when the time comes to distribute the code, they run a simple tool
which adds all the required headers to each of the source files.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

James Kuyper

On 02/23/2012 01:20 PM, Willem wrote:
....
OK, so what we need is a compiler that pre-includes all the standard
headers (AFAIK, not including a header is UB, ..

You don't need to #include a header unless you make use of something
defined in it. Even then, if what you need is a function prototype for a
standard library function, if that function can be declared without
making any of any type declared in a standard header, it is permitted
for you to not #include it, and provide your own declaration instead.
.. so the compiler is allowed
to do this) ..

That would be non-conforming. If you don't #include the standard header
(or one of headers) that is described by the standard as #defining a
given macro, you're free to use that macro's name in your own code for
just about any purpose.
 
B

BGB

What if a header that you /need/ to include starts to clash with a name in your
program. Implementations should provide a way by which you can select the
precise standard conformance. E.g. what if someone needs to build a C90
program? It's simpler to have a switch for that in the implmentation than
to update the program.


granted, yes, having to include certain headers to get certain new
symbols to be defined makes some sense.


but, IMO: if one is having lots of name clashes of this sort, then they
are likely facing with a bigger set of naming problems.

personally, I like using a system of naming conventions to try to reduce
clashes (if done well, ideally accidental clashes should be fairly rare,
both within ones' code, and with external code).

probably a big risk is when one's naming convention is something like
"word()" or "generic_words_and_underscores()", since any functions which
just happen to have a matching description will have a risk of clashing.



typically, in my case, this includes prefixing the name of the library
(and often, the component) on damn near everything.

say, when building "foolib.dll" or "foolib.so":
FOOLIB_SomeName (library-scope name);
FOOLIB_Component_SomeName (component-scoped name).

then it is mostly a matter of whether there are multiple libraries named
"foolib" (in turn leading me to use my initials as a prefix for most of
my library names, followed by more letters to identify the particular
library, say "BGBGC", "BGBDY", ...).


typically, a FirstLetterCaps convention is used for all names.

typically, global variables (if used) are all lowercase, typically using
camelCase instead (camelCase is also generally the convention for
struct-field names, but this is much less consistently followed).

internal functions typically also follow the above convention, but are
still lower-case.

other variants (typically used for methods):
libname_object_methodNameCamelCase
libname_component_object_methodNameCamelCase

sometimes, functions include suffixes, generally to indicate either the
argument types or special properties (such as 'I' for Internal, or 'R'
for Recursive). if suffixes are used, typically it is with a similar
convention to that used by OpenGL (3i, 3f, 3fv, ...).


I also sometimes use an OpenGL style naming convention
("prefixCamelCase"), generally for what are intended to be public API
functions (many older cases use all lowercase though).

granted, clashes are not entirely ruled out, for example, both my GC and
Boehm GC use the 'GC' prefix for the public API, differing mostly in
that Boehm typically uses 'GC_' whereas my GC typically uses 'gc' as
lower-case ("gctalloc()" for GC type-tagged allocation, note that
internally the prefix 'BGBGC' is used).

MS tends to use a similar convention for API functions, albeit
preferring to have an uppercase prefix (for example "WSAGetLastError()"
and similar).


also, sadly, sometimes there are exceptions, where due to laziness or
other reasons, shorter names are used, very often this means leaving off
the component or library.

LIBNAME_SomeName, when a component name "should" be included.
or:
Component_SomeName, typically for older code (before I got as rigid
about including the library name).


likewise, in a few cases "unsafe" prefixes have been used, such as
'v2'/'v3'/'v4' for some vector code (because 'v3dot' is a lot easier to
type fairly often than something like 'dyVec3DotProduct' or similar).


or such...
 
B

BartC

Quentin Pope said:
Sorry, but this is a terrible idea.

Lazy people will use this and then send their source code to someone with
a slow CPU or not much RAM... at best inconvenience, or maybe the compile
fails needlessly because of a lack of memory.

By the standards of a desktop PC, these files are relatively tiny: about
3000 lines on lccwin32, and 5000 lines on mingw. By comparison, the standard
Windows headers (excluding optional headers!) are 18000 lines and 26000
lines respectively. Plus any headers relevant to the application...

C programs may run on some very small systems, but you would expect a
development host to be reasonably respectable in computer-power.

Although it is true that the headers can contain a lot of long-winded stuff
like this, the longest header line in mingw:

_CRTALIAS long __cdecl __MINGW_NOTHROW _wfindfirsti64 (const wchar_t* _v1,
struct _wfinddatai64_t* _v2) { return(_wfindfirst32i64 (_v1,(struct
_wfinddata32i64_t*)_v2)); }

It seems to be just the nature of the language that it has to partly define
itself by reams of these tedious definitions, and written in an inefficient
text format too.

But even with the headers as they are now, with the highly-advanced
compilers that everyone is always on about, is there really no alternative
to having to read in exactly the same headers, for every single compilation,
over and over again?
Or people will use this in files that end up as modules in large
projects, where compile time is measured in hours: then reading in all
this useless crap will be a significant drain.

Only where thousands of very small source files are used, which itself is
highly inefficient.

But if it is a problem, then there is a very simple solution: replace
stdheaders.h with just the headers that are needed.
The Standard manages headers very sensibly in my opinion.

Yes, for 1972! Or maybe for an 8-bit system with 64KB.
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top