Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

preprocessor and the hash character

32 views
Skip to first unread message

Christof Warlich

unread,
Apr 25, 2016, 6:24:23 AM4/25/16
to
Hi,

the following (complete) example prints

#define HELLO
HELLO is defined

when executed:

#include <iostream>
#define PRINT(x) std::cout << #x << std::endl

int main() {
#define HELLO
PRINT(#define HELLO);
#ifdef HELLO
std::cout << "HELLO is defined" << std::endl;
#endif
return 0;
}

I'm unhappy with these two lines from this example code:

#define HELLO
PRINT(#define HELLO);

Is there any way to write a macro that expands to these two lines, expecting "#define HELLO" as parameter?

Thanks for any help. Even suggestions involving compiler specific extensions would be appreciated.

Thanks for any help,

Chris

Ben Bacarisse

unread,
Apr 25, 2016, 6:45:10 AM4/25/16
to
Christof Warlich <christof...@gmail.com> writes:

> the following (complete) example prints
>
> #define HELLO
> HELLO is defined
>
> when executed:
>
> #include <iostream>
> #define PRINT(x) std::cout << #x << std::endl
>
> int main() {
> #define HELLO
> PRINT(#define HELLO);
> #ifdef HELLO
> std::cout << "HELLO is defined" << std::endl;
> #endif
> return 0;
> }
>
> I'm unhappy with these two lines from this example code:
>
> #define HELLO
> PRINT(#define HELLO);
>
> Is there any way to write a macro that expands to these two lines,
> expecting "#define HELLO" as parameter?

You can write a macro that expands to that text, but you can't write a
macro (any macro) that expands to a directive that is "executed". The
result of macro expansion is no scanned for directives.

<snip>
--
Ben.

Öö Tiib

unread,
Apr 25, 2016, 6:50:52 AM4/25/16
to
On Monday, 25 April 2016 13:24:23 UTC+3, Christof Warlich wrote:
> Hi,
>
> the following (complete) example prints
>
> #define HELLO
> HELLO is defined
>
> when executed:
>
> #include <iostream>
> #define PRINT(x) std::cout << #x << std::endl
>
> int main() {
> #define HELLO
> PRINT(#define HELLO);
> #ifdef HELLO
> std::cout << "HELLO is defined" << std::endl;
> #endif
> return 0;
> }
>
> I'm unhappy with these two lines from this example code:
>
> #define HELLO
> PRINT(#define HELLO);


That is good that you are unhappy, preprocessor code must be ugly since
its logic is hard to follow, to debug and so is error-prone.

>
> Is there any way to write a macro that expands to these two lines, expecting "#define HELLO" as parameter?

You can not construct preprocessor directives with preprocessor macros.
Preprocessor is single pass in that regard.

C99 Standard (6.10.3.4 paragraph 3):
The resulting completely macro-replaced preprocessing token sequence is
not processed as a preprocessing directive even if it resembles one, ...

Alf P. Steinbach

unread,
Apr 25, 2016, 7:26:41 AM4/25/16
to
On 25.04.2016 12:24, Christof Warlich wrote:
>
> I'm unhappy with these two lines from this example code:
>
> #define HELLO
> PRINT(#define HELLO);
>

But what about it are you unhappy with?

Possibly you're reacting to the nonsense: the “#define” directive is not
necessary and has no effect on the PRINT.

Possibly you're reacting to the use of the preprocessor.

Possibly it strikes you as odd that something with a space in it can be
a single macro argument, but the preprocessor is a different language.

Possibly you're an experienced programmer who reacts to the formal
Undefined Behavior, “if there are sequences of preprocessing tokens
within the list of arguments that would otherwise act as preprocessing
directives, the behavior is undefined” (under the reasonable assumption
that the /intent/ was to make even a single directive-like sequence UB).

Possibly you don't like the use of simple macro names like PRINT, which
can easily collide, and would prefer e.g. MYCOMPANY_THEAPP_PRINT.

But it's practically impossible for us to narrow it down: /we are not
telepaths/.


> Is there any way to write a macro that expands to these two lines,
> expecting "#define HELLO" as parameter?

Certainly. Just do it.


> Thanks for any help. Even suggestions involving compiler specific
> extensions would be appreciated.

None needed.

But note that you can't have a generated “#define” evaluated by the
preprocessor.

Hence the generated text will be invalid as C++ code.


Cheers & hth.,

- Alf

Christof Warlich

unread,
Apr 25, 2016, 11:02:24 AM4/25/16
to
Thanks ... I see the issue that the preprocessor would need at least a second pass to accomplish what I need, which is why it can't work that way.

Honestly, I already guessed that answer, but I was still hoping that I might have missed some smart (and / or even non-standard) macro hackery: After all, some macro magic is sometimes really stunning (thinking of e.g. Boost Preprocessor).

0 new messages