Can #include use a preprocessing token?

F

Francois Grieu

Can #include safely use a preprocessing token, as in

#define HEADERFILE "stdio.h"
#include HEADERFILE
int main(void) {return printf("Hello, world\n")*0;}


TIA,

François Grieu
 
E

E. Robert Tisdale

Francois said:
Can #include safely use a preprocessing token, as in

#define HEADERFILE "stdio.h"
#include HEADERFILE
int main(void) {return printf("Hello, world\n")*0;}
> cat main.c
#define HEADERFILE "stdio.h"

#include HEADERFILE

int main(int argc, char* argv[]) {
return printf("Hello, world!\n")*0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
Hello, world!

Why, yes! It appears that you can.
 
R

Richard Bos

E. Robert Tisdale said:
Francois said:
Can #include safely use a preprocessing token, as in

#define HEADERFILE "stdio.h"
#include HEADERFILE
int main(void) {return printf("Hello, world\n")*0;}
cat main.c
#define HEADERFILE "stdio.h"

#include HEADERFILE

int main(int argc, char* argv[]) {
return printf("Hello, world!\n")*0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main
Hello, world!

Why, yes! It appears that you can.

Well, no. It appears that you can _using GCC_. Given the rather severe
embrace-and-extend habits of the Gnu people, this tells you absolutely
nothing about ISO C.

Of course, you _can_ actually do the above in ISO C, and you don't even
need a C99 compiler for that, as your command line seems to suggest. But
that conclusion can be drawn from the definition of the #include
directive in the ISO C Standard, _not_ from a test using Ganuck.

Richard
 
I

Irrwahn Grausewitz

Francois Grieu said:
Can #include safely use a preprocessing token, as in

#define HEADERFILE "stdio.h"
#include HEADERFILE
int main(void) {return printf("Hello, world\n")*0;}

Yes.

ISO/IEC 9899:1999
6.10.2 Source file inclusion
[...]
4 A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is permitted.
The preprocessing tokens after include in the directive are
processed just as in normal text. (Each identifier currently
defined as a macro name is replaced by its replacement list of
preprocessing tokens.) The directive resulting after all
replacements shall match one of the two previous forms.
[...]

Regards.
 
E

E. Robert Tisdale

Richard said:
E. Robert Tisdale said:
Francois said:
Can #include safely use a preprocessing token, as in

#define HEADERFILE "stdio.h"
#include HEADERFILE
int main(void) {return printf("Hello, world\n")*0;}
cat main.c
#define HEADERFILE "stdio.h"

#include HEADERFILE

int main(int argc, char* argv[]) {
return printf("Hello, world!\n")*0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main
Hello, world!

Why, yes! It appears that you can.

Well, no. It appears that you can _using GCC_.
Given the rather severe
embrace-and-extend habits of the Gnu people,
this tells you absolutely nothing about ISO C.

Of course, you _can_ actually do the above in ISO C,
and you don't even need a C99 compiler for that,
as your command line seems to suggest.

My command line suggests no such thing.
But that conclusion can be drawn
from the definition of the #include directive in the ISO C Standard,
_not_ from a test using Ganuck.

Pardon me Richard,
but I'll trust the GNU compiler developers
over some pretentious ass who "draws conclusions"
from his personal interpretation of the ISO C standard any day.
 
A

Arthur J. O'Dwyer

Well, no. It appears that you can _using GCC_. Given the rather severe
embrace-and-extend habits of the Gnu people, this tells you absolutely
nothing about ISO C.

In fact, AFAICT the OP's code is *not* correct. Since when is

#include "stdio.h"

the appropriate way to get a prototype in scope for 'printf', a function
defined in the header <stdio.h>? The OP's code would be perfectly
correct were he to have written

#define HEADERFILE <stdio.h>
#include HEADERFILE

-Arthur
 
A

Andrew

In fact, AFAICT the OP's code is *not* correct. Since when is

#include "stdio.h"

the appropriate way to get a prototype in scope for 'printf', a function
defined in the header <stdio.h>? The OP's code would be perfectly
correct were he to have written

#define HEADERFILE <stdio.h>
#include HEADERFILE

-Arthur

I was under the impression that "stdio.h" and <stdio.h> could both
reference the same file, but that the <> instructed the preprocessor
to look in a implementation defined location for said file, while ""
is 'look in the current directory, then in any implementation defined
locations'.

So if the pp doesn't find stdio.h in the current directory, it's well
within its rights to look elsewhere.

Am I mistaken?
 
R

Richard Bos

Arthur J. O'Dwyer said:
In fact, AFAICT the OP's code is *not* correct. Since when is

#include "stdio.h"

the appropriate way to get a prototype in scope for 'printf', a function
defined in the header <stdio.h>? The OP's code would be perfectly
correct were he to have written

#define HEADERFILE <stdio.h>
#include HEADERFILE

From (a draft of) C89:

# A preprocessing directive of the form
#
# # include "q-char-sequence" new-line
#
#causes the replacement of that directive by the entire contents of the
#source file identified by the specified sequence between the
#delimiters. The named source file is searched for in an
#implementation-defined manner. If this search is not supported, or if
#the search fails, the directive is reprocessed as if it read
#
# # include <h-char-sequence> new-line
#
#with the identical contained sequence (including > characters, if any)
#from the original directive.

Richard
 
A

Arthur J. O'Dwyer

From (a draft of) C89:
#
# A preprocessing directive of the form
#
# # include "q-char-sequence" new-line
#
#causes the replacement of that directive by the entire contents of the
#source file identified by the specified sequence between the
#delimiters. The named source file is searched for in an
#implementation-defined manner. If this search is not supported, or if
#the search fails, the directive is reprocessed as if it read
#
# # include <h-char-sequence> new-line

Okay. So it's implementation-defined whether it's correct (depending
on whether the implementation defines the search for "stdio.h" to
succeed, in which case consult your documentation, or fail, in which
case the code is correct).
Still, the portably correct way is <stdio.h>, which AFAIK is
guaranteed to succeed on any hosted implementation.

-Arthur
 
J

Jack Klein

From (a draft of) C89:

# A preprocessing directive of the form
#
# # include "q-char-sequence" new-line
#
#causes the replacement of that directive by the entire contents of the
#source file identified by the specified sequence between the
#delimiters. The named source file is searched for in an
#implementation-defined manner. If this search is not supported, or if
#the search fails, the directive is reprocessed as if it read
#
# # include <h-char-sequence> new-line
#
#with the identical contained sequence (including > characters, if any)
#from the original directive.

Richard

Your quotation is basically correct, but your conclusion is not,
according to the standard. It happens to work on most
implementations, because the C standard headers are supplied as text
files for the majority of them.

Here is the relevant text from the C99 standard, including material
above what you quoted:

<begin quote>
6.10.2 Source file inclusion

Constraints
1 A #include directive shall identify a header or source file that can
be processed by the implementation.

Semantics
2 A preprocessing directive of the form
# include <h-char-sequence> new-line
searches a sequence of implementation-defined places for a header
identified uniquely by the specified sequence between the < and >
delimiters, and causes the replacement of that directive by the entire
contents of the header. How the places are specified or the header
identified is implementation-defined.

3 A preprocessing directive of the form
# include "q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the
source file identified by the specified sequence between the "
delimiters. The named source file is searched for in an
implementation-defined manner. If this search is not supported, or if
the search fails, the directive is reprocessed as if it read
# include <h-char-sequence> new-line
with the identical contained sequence (including > characters, if any)
from the original directive.
<end quote>

Note the distinction between "headers" (which need not be files) which
are included with the #include <> directive, and source files which
may be included with the #include "" directive.

There is no guarantee that:

#include "stdio.h"

....will include the standard C header <stdio.h> into the source and
make the corresponding library functions available with proper
prototypes.

Specifically, if the implementation-defined methods of search and file
or file identification happen to come across some random file _not_
provided by the implementation as a standard header, and includes it
as a source file, the behavior is completely undefined.

#include <stdio.h>

....is conforming and guaranteed to properly include the standard
header.

#include "stdio.h"

....is not, and is not required to be accepted by a conforming
implementation.

This is true of all 15, 18, or 24 standard headers for C89/90, 95, and
99 respectively.
 
R

Richard Bos

Jack Klein said:
Your quotation is basically correct,

It is perfectly correct; it is a direct copy and paste. It is not,
however, C99.
Here is the relevant text from the C99 standard, including material
above what you quoted:

<begin quote>
6.10.2 Source file inclusion

[ Snip quote ]
Note the distinction between "headers" (which need not be files) which
are included with the #include <> directive, and source files which
may be included with the #include "" directive.
Specifically, if the implementation-defined methods of search and file
or file identification happen to come across some random file _not_
provided by the implementation as a standard header, and includes it
as a source file, the behavior is completely undefined.

Ah, but...

# [#3] If a file with the same name as one of the above < and
# > delimited sequences, not provided as part of the
# implementation, is placed in any of the standard places that
# are searched for included source files, the behavior is
# undefined.

That's from n869, 7.1.2. C99 has the same text, AFAIK.

So if that file is found, _that file_ causes the undefined behaviour.
For an otherwise well-conforming program, i.e. one which does _not_ have
this UB-causing file, #include "stdio.h" is required to fall through to
<stdio.h>.

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top