Skip to main content
We’ve updated our Terms of Service. A new AI Addendum clarifies how Stack Overflow utilizes AI interactions.
Code Golf

Return to Answer

Commonmark migration
Source Link

##JavaC++C, 363/27 = 13.4....

JavaC++C, 363/27 = 13.4....

##JavaC++C, 363/27 = 13.4....

JavaC++C, 363/27 = 13.4....

added 1 character in body
Source Link
user45941
user45941

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.

Source Link
user45941
user45941

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

AltStyle によって変換されたページ (->オリジナル) /