##JavaC++C, 363/27 = 13.4....
JavaC++C, 363/27 = 13.4....
##JavaC++C, 363/27 = 13.4....
JavaC++C, 363/27 = 13.4....
Java prints 1, C++ prints 2, C prints 3. Not winningbreaking any records here (because Java), but I really like the clever, abusive way of making a polyglot in these languages that I discovered.
Java prints 1, C++ prints 2, C prints 3. Not winning any records here (because Java), but I really like the clever, abusive way of making a polyglot in these languages that I discovered.
Java prints 1, C++ prints 2, C prints 3. Not breaking any records here (because Java), but I really like the clever, abusive way of making a polyglot in these languages that I discovered.
##JavaC++C, 363/27 = 13.4....
Java prints 1, C++ prints 2, C prints 3. Not winning any records here (because Java), but I really like the clever, abusive way of making a polyglot in these languages that I discovered.
//\u000a/*
#include<stdio.h>
#ifdef __cplusplus
#define o "2"
#else
#define o "3"
#endif
int p(int a){printf(o);}
struct{int(*print)(int);}out;
//*/
/*\u002a/
import static java.lang.System.out;
public class P{//*/
/*\u002a/public static void//*/
main(/*\u002a/String[] args//*/
){//\u000a/*
out.print=p;
//\u002a/
out.print(1);}
/*\u002a/}//*/
This is a mess. Here's a breakdown of how it works. The Unicode literals (\u000a, otherwise known as a linefeed, and \u002a, otherwise known as *) are expanded by the Java compiler into their actual characters. So, here is what the Java compiler sees:
//
/*
#include<stdio.h>
#ifdef __cplusplus
#define o "2"
#else
#define o "3"
#endif
int p(int a){printf(o);}
struct{int(*print)(int);}out;
//*/
/**/
import static java.lang.System.out;
public class P{//*/
/**/public static void//*/
main(/**/String[] args//*/
){//
/*
out.print=p;
//*/
out.print(1);}
/**/}//*/
All that stuff in the beginning is ignored because it's all wrapped in a multi-line comment (/* ... */). Later on, we see that mixing single-line and multi-line comments allows us to control exactly which parts are commented out in each language. In the main method, we start a multi-line comment, and then have //*/. Ordinarily, this would be a single-line comment, but since we are in a multi-line comment, the // doesn't do anything, allowing the */ to close it.
This is the equivalent Java code, with comments removed:
import static java.lang.System.out;
public class P{
public static void
main(String[] args
){
out.print(1);}
}
Here is what the C/C++ compiler sees (I've removed the Unicode literals, since they are not expanded by the compiler and thus don't do anything):
///*
#include<stdio.h>
#ifdef __cplusplus
#define o "2"
#else
#define o "3"
#endif
int p(int a){printf(o);}
struct{int(*print)(int);}out;
//*/
/*/
import static java.lang.System.out;
public class P{//*/
/*/public static void//*/
main(/*/String[] args//*/
){//\/*
out.print=p;
///
out.print(1);}
/*/}//*/
Here, the single-line comments override the multi-line comment delimiters in the beginning, so all of the #defines and the #include get preprocessed. Next, multi-line comments are used to comment out the boiletplate code for Java. This is the equivalent code, with comments removed:
#include<stdio.h>
#ifdef __cplusplus
#define o "2"
#else
#define o "3"
#endif
int p(int a){printf(o);}
struct{int(*print)(int);}out;
main(
){
out.print=p;
out.print(1);}
A standard C/C++ polyglot trick (the #ifdef __cplusplus) is utilized to define a token o as either "2" or "3", depending on if it's a C++ or a C compiler that is compiling the code. Next, we define a funtion p that takes a single (ignored) int argument and calls printf, using our newly-defined o token. As per usual, the return value is left out, since we're not in strict mode. Next, we define a struct with a single member, a function pointer whose signature matches p's, and construct a single instance named out. In the main method (we leave off the int as usual), the address of p is assigned to out.print (so calling out.print calls p), and it is called.
If C++ wasn't included in the languages, we could drop all of the preprocessor code, and define p as int p(int a){puts("2");}. Unfortunately, C++ requires an #include to do I/O. If C wasn't included, we could drop the definition of p and the #ifdef preprocessor macro, and directly define a member function in the struct instead of needing a function pointer. Unfortunately, C does not support member functions.