##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.