How does this code print 404?

I copied this below code from Stack Overflow's 404 Not Found Error Page .

# define v putchar
# define print(x)
main(){v(4+v(v(52)-4));return 0;}/*
#>+++++++4+[>++++++<-]>
++++.----.++++.*/
print(202*2);exit();
#define/*>.@*/exit()

The above code compiles fine and prints 404 on the console. I thought the statement print(202*2); is responsible for printing 404 , but I am not right because changing the numbers in this statement also prints 404 .

Could somebody help me to understand this code and how it prints 404 ?

Am posting the compilation output for your reference as there are comments saying this code doesn't compile. The file containing above code is Test.c .

gcc Test.c -o Test

Test.c:3:1: warning: return type defaults to 'int' [-Wimplicit-int] main(){v(4+v(v(52)-4));return 0;}/* ^ Test.c: In function 'main': Test.c:1:12: warning: implicit declaration of function 'putchar' [-Wimplicit-function-declaration] # define v putchar ^ Test.c:3:8: note: in expansion of macro 'v' main(){v(4+v(v(52)-4));return 0;}/* ^ Test.c: At top level: Test.c:6:14: warning: data definition has no type or storage class print(202*2);exit(); ^ Test.c:6:14: warning: type defaults to 'int' in declaration of 'exit' [-Wimplicit-int] Test.c:6:14: warning: conflicting types for built-in function 'exit'

./Test

404


# define v putchar

this defines v as the putchar() function. It prints a character and returns it.

# define print(x)

this defines print(x) as nothing (so print(202*2) means nothing)

main(){v(4+v(v(52)-4));return 0;}/*

this could be rewritten as:

main()
{
  putchar(4 + putchar(putchar(52) - 4));
  return 0;
}

it is using ASCII codes to print '4' (code 52), '0' (code 52 - 4 = 38) and again '4', so "404".

That line ends with a /* starting a comment the continues through the next two lines:

#>+++++++4+[>++++++<-]>
++++.----.++++.*/

The line below turns out empty, but it is a bit tricky because exit() is defined as empty AFTER the line itself. That works because the C preprocessor runs BEFORE the compilation.

print(202*2);exit();

The line below defines exit() as empty, used on the line above.

#define/*>.@*/exit()

Cannot use a meta-question as dupe, so blatantly copying from the MSO answer.

Since this is tagged c and mentioned "compiled", so just extracting the C part of it.

Credits: Mark Rushakoff is the original author of the polyglot.

The C code is fairly easy to read, but even easier if you run it through a preprocessor:

main(){putchar(4+putchar(putchar(52)-4));return 0;};exit();

Your standard main function is declared there, and exit is also declared as a function with an implicit return type of int ( exit is effectively ignored).

putchar was used because you don't need any #include to use it; you give it an integer argument and it puts the corresponding ASCII character to stdout and returns the same value you gave it. So, we put 52 (which is 4 ); then we subtract 4 and output 0 ; then we add 4 to output 4 again.

Also, a little more elboration, from [Cole Johnson's] (https://meta.stackoverflow.com/users/1350209/cole-johnson) answer

Disregarding all of that, when we reformat the code a bit, and replace 52 with its ASCII equivalent ( '4' ), we get:

int main() {
    putchar(4 + putchar(putchar('4') - 4));
    return 0;
}

As for the putchar declaration, it is defined by the standard to return it's input, like realloc . First, this program prints a 4 , then takes the ASCII value ( 52 ), subtracts 4 ( 48 ), prints that (ASCII 0 ), adds 4 ( 52 ), prints that ( 4 ), then finally terminates. This results in the following output:

404

As for this polyglot being valid C++ , unfortunately, it is not as C++ requires an explicit return type for functions. This program takes advantage of the fact that C requires functions without an explicit return type to be int .


The code cannot compile on a standard C compiler, such as gcc -std=c11 -pedantic-errors .

1) main must return int on hosted systems.
2) putchar() must have #include <stdio.h> .
3) You can't write semicolons outside functions.

After fixing these beginner-level bugs and removing all superfluous fluff that doesn't do anything but creating compiler errors, we are left with this:

#include <stdio.h>
#define v putchar
int main(){v(4+v(v(52)-4));return 0;}

This revolves around putchar returning the character written:

putchar(4+putchar(putchar(52)-4));
  • 52 is ASCII for '4' . Print 4.
  • 52 - 4 = 48, ASCII for 0 . Print 0.
  • 4 + 48 = 52. Again print 4.
  • And that's it. Very bleak as far as obfuscation attempts go.


    Proper, standard-compliant obfuscation would rather look something like this:

    #include <stdio.h>
    #include <iso646.h>
    
    ??=define not_found_404(a,b,c,d,e,f,g,h,i,j)a%:%:b%:%:c%:%:d%:%:e%:%:f(
    (g%:%:h%:%:i%:%:j<::>)<%'$'+d##o%:%:e not "good",g??=??=ompl ??-- -0163l,
    ((void)(0xBAD bito##b not "bad"),not "ugly")??>,(g%:%:h%:%:i%:%:j??(??)){
    ((c%:%:d%:%:e)- -not "lost")     <:??=a??) -??-??- '<',
    ((c%:%:d%:%:e)- -not "found")    <:??=b??) -??-??- 'B',
    ((c%:%:d%:%:e)- -not 0xDEADC0DE) <:??=c??) -??-??- '5',
    ((c%:%:d%:%:e)- -6##6##6 xo##b- -6##6##6)%>)
    
    int main()
    {
      not_found_404(p,r,i,n,t,f,c,h,a,r);  
    }
    
    链接地址: http://www.djcxy.com/p/73606.html

    上一篇: 未定义的参考`pthread

    下一篇: 这段代码如何打印404?