Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ program
1. Abuse C++ automatic typedef
s
(Note that the struct
needs to be declared in an inner scope so that it takes precedence over the outer name in C++.)
#include <stdio.h>
int main(void)
{
char x;
{
struct x { char dummy[2]; };
printf("%s\n", sizeof (x) == 1 ? "C" : "C++");
}
}
A similar version that doesn't rely on the ambiguity between sizeof (type)
and sizeof (variable)
, using only types:
#include <stdio.h>
int main(void)
{
typedef char t;
{
struct t { char dummy[2]; };
printf("%s\n", sizeof (t) == 1 ? "C" : "C++");
}
}
2. Abuse C++ struct
/class
equivalence, automatic typedef
s, and automatically-generated default constructors
#include <stdio.h>
int isC = 0;
void Foo() { isC = 1; }
int main(void)
{
struct Foo { int dummy; };
Foo();
printf("%s\n", isC ? "C" : "C++");
}
3. Abuse nested struct
declarations in C
Also see Symbol clashing of inner and outer structs, C++ vs C
#include <stdio.h>
int main(void)
{
typedef struct inner { int dummy; } t;
{
struct outer { struct inner { t dummy[2]; } dummy; };
printf("%s\n",
sizeof (struct inner) == sizeof (t)
? "C++"
: "C");
}
}
4. Abuse //
comments
This won't work with C99 or with C89 compilers that support //
as an extension.
#include <stdio.h>
int main(void)
{
printf("%s\n",
0 //* */
+1
? "C++"
: "C");
}
or alternatively:
printf("%s\n",
1 //* */ 2
? "C++"
: "C");
5. sizeof
differences with char
literals
Note that this isn't guaranteed to be portable since it's possible that some hypothetical platform could use bytes with more than 8 bits, in which case sizeof(char)
could be the same as sizeof(int)
. (Also see Can sizeof(int) ever be 1 on a hosted implementation?)
#include <stdio.h>
int main(void)
{
printf("%s\n", sizeof 'a' == 1 ? "C++" : "C");
}
6. Abuse differences in when lvalue⇒rvalue conversions are performed
This is based off of the 5.16, 5.17, 5.18 example in the ISO C++03 standard, and it works in gcc but not in MSVC (possibly due to a compiler bug?).
#include <stdio.h>
int main(void)
{
void* array[2];
printf("%s\n",
(sizeof (((void) 0), array) / sizeof (void*) == 1)
? "C"
: "C++");
}
7. Abuse differences in the way C and C++'s grammars parse the ternary operator
This one isn't strictly legal, but some compilers are lax.
#include <stdio.h>
int main(void)
{
int isCPP = 1;
printf("%s\n", (1 ? isCPP : isCPP = 0) ? "C++" : "C");
}
(You also could check for the __cplusplus
preprocessor macro (or various other macros), but I think that doesn't follow the spirit of the question.)
I have implementations for all of these at: http://www.taenarum.com/csua/fun-with-c/c-or-cpp.c
We had to do a similar assignment at school. We were not allowed to use preprocessor (except for #include
of course). The following code uses the fact that in C, type names and structure names form separate namespaces whereas in C++ they don't.
#include <stdio.h>
typedef int X;
int main()
{
struct X { int ch[2]; };
if (sizeof(X) != sizeof(struct X))
printf("C\n");
else
printf("C++\n");
}
Simple enough.
#include <stdio.h>
int main(int argc, char ** argv) {
#ifdef __cplusplus
printf("C++\n");
#else
printf("C\n");
#endif
return 0;
}
Or is there a requirement to do this without the official standard?