Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can #endif in an included file be used to close a #if in the including file?

Let's say I have two files, a.h:

#if 1
#include "b.h"

and b.h:

#endif

Both gcc's and clang's preprocessors reject a.h:

$ cpp -ansi -pedantic a.h >/dev/null
In file included from a.h:2:0:
b.h:1:2: error: #endif without #if
 #endif
  ^
a.h:1:0: error: unterminated #if
 #if 1
 ^

However, the C standard (N1570 6.10.2.3) says:

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.

which appears to permit the construct above.

Are gcc and clang not compliant in rejecting my code?

like image 947
whitequark Avatar asked Sep 29 '15 15:09

whitequark


People also ask

Can be means?

—used to say that what a person does or feels is understandable or that a person should not be blamed for doing or feeling something.

CAN is noun or verb?

can (verb) can–do (adjective) canned (adjective)

Can is an verb?

The verb “can” belongs to the second group. This verb is one of the most used in the English language, and it has a variety of uses so wide that sometimes is hard to keep up! Usually, “can” is considered one of the most strange verbs in English.

Can noun in a sentence?

She sipped from a can of Coke. The floor was littered with empty food cans. This special type of milk comes in a can. We opened a can of sardines for lunch.


1 Answers

The C standard defines 8 translation phases. A source file is processed by each of the 8 phases in sequence (or in an equivalent manner).

Phase 4, as defined in N1570 section 5.1.1.2, is:

Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. If a character sequence that matches the syntax of a universal character name is produced by token concatenation (6.10.3.3), the behavior is undefined. A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.

The relevant sentence here is:

A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively.

which implies that each included source file is preprocessed by itself. This precludes having a #if in one file and the corresponding #endif in another.

(As "A wild elephant" mentioned in comments, and as rodrigo's answer says, the grammar in section 6.10 also says that an if-section, which starts with a #if (or #ifdef or #ifndef) line and ends with a #endif line, can only appear as part of a preprocessing-file.)

like image 105
Keith Thompson Avatar answered Sep 22 '22 11:09

Keith Thompson