cquine

Quine Program Example in C


In my course slides, I have this example but without much explanation:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}

I understand what quine programs in general mean but I do not quite understand what's happening in the code above. This is the output I get if I run it:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}

But how is it reproducing its own code? I don't really understand how the output is produced.


Solution

  • Start by writing it out in a way that'll be clearer (not changing anything but the layout):

    char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";
    
    main()
    {
        printf(f,34,f,34,10);
    }
    

    So we see a main function as we'd expect (it should return an int but you're allowed to get away with not in C; likewise for no function arguments). And before that, a regular string. It's a funny-looking string, but it is not really that different to char*f="fish";.

    Okay, so what if we expand the printf by putting the string in there by hand?

    printf("char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c" ,34,f,34,10);
    

    We can see that it's going to print out some guff, and substitute in some values along the way. They are:

     First %c : 34   (the ASCII code for " (quotes))
     First %s : 'f'  (our string, once again)
    Second %c : 34   (" again) 
     Third %c : 10   (the ASCII code for Newline)
    

    Let's substitute those all in then too (though I've replaced the contents of the string with <the string>, and "'s with \"'s to make it actually work as a standalone statement):

    main()
    {
        printf("char*f=\"<the string>\";main(){printf(f,34,f,34,10);}\n");
    }
    

    Well look at that! main simply prints out the line we first started with. Hurrah!


    Edited to add:

    Although I've basically spelled out the answer for you, there is still a puzzle remaining. Consider for yourself why we bother substituting in the 34, f, 34, 10, rather than just putting them directly into the string like I did in my final code.