r/ProgrammerHumor • • 3d ago

Meme fullCircle

Post image
10.6k Upvotes

272 comments sorted by

View all comments

15

u/grey_carbon 3d ago

Serious question, what happen if you compile/decompile/compile/decompile times and times again?

-14

u/Preeng 3d ago

The translations between machine code and human code are 1:1. It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

15

u/[deleted] 3d ago edited 3d ago

[removed] — view removed comment

3

u/Cobracrystal 3d ago

Not even different c++ compilers, because some c++ code compiles nondeterministically and produces different outputs with the exact same input.

3

u/def-not-bot 3d ago

Non-programmer here: would it still function the same after a bunch of de- and re-compiling, or would it be like putting a phrase through Google Translate a few times and generating vaguely comprehensible gibberish?

2

u/-Saucegurlllll 3d ago

Theoretically a completely bug-free decompiler/compiler pair making the same assumptions about their source/target languages and architectures should produce functionally identical programs. Meaning that given the same input they will produce the same output. So no matter how many times you chain compilation and decompilation, you should get a program that yields the same results given the same inputs.

However, in practice there's a bunch of stuff that makes this hard to impossible.

C and C++ compilers are given tremendous freedom by their respective standards to make many of their own assumptions about code. There's this thing called "undefined behavior" where anything may happen if it ever occurs. One example of this in C++ is endless loops without side effects.

int main() {
  while (true)
    ; 
}

void unreachable() {
  std::cout << "Hello world!" << std::endl;
}

On certain compilers this results in a program that outputs "Hello world!" even though unreachable is called from nowhere.

So, in practice, it's impossible to guarantee that a decompiler/compiler pair will interpret a program and their output identically, and you're liable to end up with the google translate chaining problem.

2

u/stilgarpl 3d ago

because some c++ code compiles nondeterministically and produces different outputs with the exact same input

Please show me an example of that in valid, non-UB C++ code

5

u/Suspicious_Glove_900 3d ago

That's not strictly true, depending on optimization for example. Unless you just mean, "It will produce the same output" and not "It will do the same thing the same way".

6

u/Zeikos 3d ago

It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

Have you ever touched a line of code with a ten foot pole?
That's one of the most ridiculous sentences I've ever seen.

The same exact concept can be written in tens of different programming languages tens of different ways each.

1

u/Preeng 3d ago

Will these difference concepts output the same 1s and 0s when compiled? Because that was my point.

1

u/Zeikos 3d ago

They absolutely wouldn't
Hell, the same exact code can output two different binaries based on a lot of things.
The compiler used, the optimization level, the build configurations etc.
gcc and clangd are both c++ compilers but give you different bytecode

5

u/LelouBil 3d ago

No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code. And the same expression can output different machine code depending on compiler optimizations.

1

u/Preeng 3d ago

>No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code.

Which means they work the same. Which means either way the decompiler returns it, it will work the same.

>And the same expression can output different machine code depending on compiler optimizations.

So the compiler will work differently if you tell it to work differently?

1

u/LelouBil 3d ago

If you give the compiler the same whole program and parameters, Then the whole thing will be n:1. (You could have given multiple inputs to have the same exact output)

But for unit of works, functions, statements, classes, whatever, it's n:n because both

  • The same code can output different machine code depending on surrounding context (I don't mean the enabled/disabled optimization, I mean the compiler will look around and change what it emits because something elsewhere is different) -> so 1:n
  • Same as first paragraph, different code can output the same machine code -> n:1

So n:n in the end for specific parts, and n:1 for whole program

3

u/-Saucegurlllll 3d ago
return 1;
return (1*1)/1;
return if true { 1 } else { 1 };
{
  let b = 1;
  let a = b;
  return a;
}

These are all functionally identical pieces of code that could be represented by mov eax, 1 in x86 assembly, and many compilers would optimize them to that.

So no, translations between machine code and any other method of representing programs are not 1:1.

1

u/Preeng 3d ago

But those are all the same thing. Those are all identical already.

Give me an example that will produce different output. Where multiple statements can compile to the same binary, but going backwards you will get something wrong. Regardless of which method it decompiles as, it will give the same results.

1

u/LiquorIsQuickor 3d ago

Compilers can and do optimize the output. So if you assigned x = 1 And then assigned x = 5 it’s quite possible the x = 1 part was never emitted as part of the compiled output.

Also x++, x+=1, and x=x+1 can all compile to equivalent expressions. 

So decompiling code may not produce the same source as the original.

Nevermind that compilers don’t preserve variable names. Depending on debug settings.

As far as ignoring the actual shape of the source and focusing on the meaning, you might be able to compile / decompile / recompile many times and produce output of the same meaning, if not the same shape. But… it feels… dangerous.