C/C++ preprocessor directives

This is a discussion on C/C++ preprocessor directives within the C++ Programming forums, part of the General Programming Boards category; Which of the following statements correctly describe C preprocessor directives in C++?
A. Preprocessor directives are processed before macros are ...

C/C++ preprocessor directives

Which of the following statements correctly describe C preprocessor directives in C++?

A. Preprocessor directives are processed before macros are expanded.
B. Any number of #else directives can be used between an #if and an #endif.
C. The #pragma directive is machine-independent.
D. The #import directive is used to copy code from a library into the
program's source code.
E. The #include directive is used to identify binary files that will be
linked to the program.

Well I'm sure I know all these, but am a little unsure about A and C. Now:
* From memory, macros are processed before directives, so A is INCORRECT.
* B is INCORRECT because you can't do #if #else #else #endif
* C is CORRECT since "The #pragma directives offer a way for each compiler to offer machine- and operating system-specific features while retaining overall compatibility with the C and C++ languages." from http://msdn.microsoft.com/en-us/libr...05(VS.71).aspx
* D is obviously CORRECT
* E is obviously CORRECT

Not quite. Who is giving you these awful questions? They need to spend more time teaching good design/coding techniques.

A. I don't know about A. Isn't the expanding of macros part of the preprocessor?
B. You're right.
C. Read the first paragraph of the page you linked to.
D. Never used it.
E. Binary? Linking? No -- #include expands one text file into another.

So there's my two cents. Now stick around while one of the gurus corrects us.

Tell me about it. My guess is this online quiz was setup by a webdev coder and as we all know they don't really know about real coding - and hence have developed crap questions - but I must say its had the hardest (or hardest to understand) questions I've found online.

Originally Posted by CodeMonkey

A. I don't know about A. Isn't the expanding of macros part of the preprocessor?

Yep, the preprocessor expands macros and directives, but the order of expansion (or IIRC the correct term is "Phases of Translation") is what the question is asking (Well that is how I read it).

1. It's hard to say whether macros or directives come first. The standard reads as though they happen together, from the start of the file to the end.

4. It's kind of hard to say what #import does, since it doesn't exist. (Objective-C++ uses it, and there it it's more-or-less #include with guards built in; any file that is #imported is only ever included once, no matter how often it appears in the file.)

Well, yes, but (1) #define is a preprocessor directive, and (2) order still matters -- if WIN32 is defined after that piece of code, PATH_SEPARATOR will still be /. Think of how WIN_LEAN_AND_MEAN has to be defined before you include <windows.h>, or how NDEBUG has to be defined before <assert.h> if you want to disable assertions.

Statement A is incorrect (and, in fact, meaningless). Preprocessor directives and macro expansions are processed sequentially from beginning to end of a compilation unit. So processing of preprocessor directives can be interleaved with macro expansions.

Statement B is ambiguous. It is possible to nest #if/#elif/#else directives. The wording of the question does not exclude nesting. If nesting is not excluded, the statement is correct. Otherwise, the statement is incorrect.

Statement C is ambiguous. The #pragma directive itself is machine independent. However, the results of using particular pragmas are compiler dependent. There are no standard pragmas.

Statement D is incorrect. #import is not a standard preprocessor directive. It is a non-standard extension supported by some compilers.

Statement E is incorrect. The preprocessor replaces the #include directive with the text of the specified file. It has nothing to do with identifying binary files to be linked to the program.

Well, yes, but (1) #define is a preprocessor directive, and (2) order still matters -- if WIN32 is defined after that piece of code, PATH_SEPARATOR will still be /. Think of how WIN_LEAN_AND_MEAN has to be defined before you include <windows.h>, or how NDEBUG has to be defined before <assert.h> if you want to disable assertions.

Sure, if you put it that way then #1 is false. I was thinking about it in a smaller scope, such as one #if/#endif block, where other macros were already expanded above it...
I'd have to agree that the questions are very badly worded and ambiguous.

A) Incorrect. This happens at the same time. In particular, it is implementation-specific whether macros in an #error directive are expanded, if I remember correctly. However, you cannot form preprocessor directives by expanding macros (except the C99 _Pragma preprocessor keyword), so this may be what the web quiz wants to know.

B) What grumpy said. There can be only one #else associated with an #if (but any number of #elifs), but lexically there can be as many #elses between an #if and its #endif as the compiler allows to nest.

C) What grumpy said.

D) There is no #import directive in the standard. Objective-C (and Objective-C++) use #import as a sort of guarded #include, and GCC makes this available to C and C++ programs as well, I think. The MS compiler uses #import as basically, "generate a header file from this COM type library and include it". It's also used to reference .Net assemblies in C++/CLI.

Horrible question/answer selection, but the answer is obviously A simply by the wording (it describes preprocessor directives correct or not, while the other choices are feature statements - and all incorrect anyway). Unless the author incredibly misunderstood an intro tutorial (since they usually start with #include) and it's E.