Different behavior of C/C++-preprocessor

A

Alex Vinokur

Hi,

Hi,

Different C/C++-preprocessors have diffrerent behavior on this program.

Is there any preprocessor standard for this case?

// ========================
// File foo.cpp

#define MACRO1(x) x
#define MACRO2(x) x

int main()
{
MACRO1(
#if 1
MACRO2("ABC")
#else
MACRO2("XYZ")
#endif
);
return 0;
}

// ========================



========= Linux =========
// Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.4.191 Build 20110427
icpc -E foo.cpp

----- Output of preprocessing -----

# 1 "foo.cpp"
int main()
{
"ABC";
# 13 "foo.cpp"
return 0;
}n 0;
}

========================



========= Windows =========
// Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
cl /E foo.cpp

----- Output of preprocessing -----

#line 1 "foo.cpp"

int main()
{
#if 1 "ABC" #else "XYZ" #endif;
#line 13 "foo.cpp"
return 0;
}

===========================
 
V

Victor Bazarov

Different C/C++-preprocessors have diffrerent behavior on this program.

Is there any preprocessor standard for this case?

There is but one Standard, ISO/IEC 14882:2011. It defines how the text
of a C++ program is preprocessed. See subclause 2.2 and subclause 16.3.
// ========================
// File foo.cpp

#define MACRO1(x) x
#define MACRO2(x) x

int main()
{
MACRO1(
#if 1
MACRO2("ABC")
#else
MACRO2("XYZ")
#endif
);

Here you have directives (#if, #else and #endif) appear inside a macro
*invocation*. According to [cpp.replace/11], which says "If there are
sequences of preprocessing tokens within the list of arguments that
would otherwise act as preprocessing directives,155 the behavior is
undefined", the behavior of the preprocessor is not defined by the
Standard for your code. I think you're lucky they don't format your
hard drive or email obscene photos to your boss on your behalf.
return 0;
}

// ========================



========= Linux =========
// Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.4.191 Build 20110427

----- Output of preprocessing -----

# 1 "foo.cpp"
int main()
{
"ABC";
# 13 "foo.cpp"
return 0;
}n 0;
}

========================



========= Windows =========
// Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

----- Output of preprocessing -----

#line 1 "foo.cpp"

int main()
{
#if 1 "ABC" #else "XYZ" #endif;
#line 13 "foo.cpp"
return 0;
}

===========================

V
 
J

Juha Nieminen

Victor Bazarov said:
I think you're lucky they don't format your
hard drive or email obscene photos to your boss on your behalf.

No, they are. Because else they would be flooded with lawsuits.
 
W

W Karas

.
Here you have directives (#if, #else and #endif) appear inside a macro
*invocation*. According to [cpp.replace/11], which says "If there are
sequences of preprocessing tokens within the list of arguments that
would otherwise act as preprocessing directives,155 the behavior is
undefined", the behavior of the preprocessor is not defined by the
Standard for your code. I think you're lucky they don't format your
hard drive or email obscene photos to your boss on your behalf.

Victor, Victor, where's the love?
 
V

Victor Bazarov

Here you have directives (#if, #else and #endif) appear inside a macro
*invocation*. According to [cpp.replace/11], which says "If there are
sequences of preprocessing tokens within the list of arguments that
would otherwise act as preprocessing directives,155 the behavior is
undefined", the behavior of the preprocessor is not defined by the
Standard for your code. I think you're lucky they don't format your
hard drive or email obscene photos to your boss on your behalf.

Victor, Victor, where's the love?

In the air, I'm guessing...
 
W

W Karas

On 7/25/2012 12:23 AM, W Karas wrote:
> On Monday, July 16, 2012 10:53:13 AM UTC-4, Victor Bazarov wrote:
> ...
>> Here you have directives (#if, #else and #endif) appear inside a macro
>> *invocation*. According to [cpp.replace/11], which says "If there are
>> sequences of preprocessing tokens within the list of arguments that
>> would otherwise act as preprocessing directives,155 the behavior is
>> undefined", the behavior of the preprocessor is not defined by the
>> Standard for your code. I think you're lucky they don't format your
>> hard drive or email obscene photos to your boss on your behalf.
>
> Victor, Victor, where's the love?
>

In the air, I'm guessing...

You seem to be holding your breath :eek:) .
 
J

James Kanze

Different C/C++-preprocessors have diffrerent behavior on this program.

Only when you use extensions.
Is there any preprocessor standard for this case?

I presume you're using an option to request preprocessor output
from the compiler. The standard says nothing about this, and in
fact, doesn't even require such an option.

Judging from the output you post, it looks like the option you
used with Microsoft doesn't do full preprocessing, but rather
outputs some internal format with some preprocessing directives
not yet expanded. It's not what I'd normally expect, but
there's certainly nothing you can say against it from a
standards point of view.
 
J

James Kanze

On 7/15/2012 12:43 AM, Alex Vinokur wrote:
There is but one Standard, ISO/IEC 14882:2011. It defines how the text
of a C++ program is preprocessed. See subclause 2.2 and subclause 16.3.

It defines how the entire program is translated to an executable. He's
apparently using some (very common) option to dump some (not necessarily
well defined) internal state of the compiler.
Here you have directives (#if, #else and #endif) appear inside a macro
*invocation*. According to [cpp.replace/11], which says "If there are
sequences of preprocessing tokens within the list of arguments that
would otherwise act as preprocessing directives, the behavior is
undefined", the behavior of the preprocessor is not defined by the
Standard for your code. I think you're lucky they don't format your
hard drive or email obscene photos to your boss on your behalf.

That's an interesting quote. I wasn't aware of this restriction. As a
programmer, of course, I'd never write code like this. I like my code
to be readable and maintainable. But I wasn't aware that it was
illegal. Thanks for pointing it out to me; I've yet another argument
against such junk.

In practice, I expect that most compilers "do the right thing" in this
case. I'm afraid that there are tons of legacy C code which counts on
it. (I can recall 8 deep nesting of #if to make a single token
conditional in some older Unix headers.)

It would be interesting if we had a valid test of something
which might be (or have been) defined by the standard.
Something along the lines of:

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

int
main()
{
PRINT(
#if 1
"ABC"
#else
"XYZ"
#endif
);
return 0;
}


Does this compile and generate an executable? If so, what does
it output?
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top