Different C-preprocessors have diffrerent behavior

A

Alex Vinokur

Hi,

Different C-preprocessors have diffrerent behavior on this program.

Is there any preprocessor standard for this case?

// ========================
// File foo.c

#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
icc -E foo.c

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

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

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



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

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

#line 1 "foo.c"

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

===========================
 
A

Alan Curry

Hi,

Different C-preprocessors have diffrerent behavior on this program.

Is there any preprocessor standard for this case?

I'm afraid not. The standard says this about expansion of function-like
macros (macros with arguments):

If there are sequences of preprocessing tokens within the list of arguments
that would otherwise act as preprocessing directives, the behavior is
undefined.

(section 6.10.3 paragraph 11)

gcc -pedantic would have warned you about it.
// ========================
// File foo.c

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

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

You'll have to make MACRO1 a function, or factor out the #if so that it
covers the entire invocation of MACRO1, like this:

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

Actually, the semicolon isn't within the problem area so it doesn't need to
be repeated in both branches, but I think a bare semicolon after an #endif
would be stylistically unfortunate:

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

Or refactor it another way:

#if 1
#define arg "ABC"
#else
#define arg "XYZ"
#endif
MACRO1(MACRO2(arg));

Or even:

MACRO1(1?MACRO2("ABC"):MACRO2("XYZ"));

i.e. trust the compiler to figure out that one of those branches is
unreachable and optimize it out.
 

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,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top