The Classic C Quine
By Susam Pal on 19 Oct 2003
I have been running a mailing list named ncoders for the last several months now. This mailing list is meant for university students interested in computers, programming, and network protocols.
A few weeks ago, one of the members of our mailing list introduced us to an interesting type of computer program called quine. A quine is a computer program that produces an exact copy of its own source code as its output. It must not consume any input, so tricks involving reading its own source code and printing it are not permitted.
The Classic Quine
Here is a classic quine Vikram shared with us while explaining the concept of quine:
main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);}
This program is written in K&R C. The current version of GCC compiles it fine. It is a valid quine on ASCII machines because this program uses the integer code 34
to print the quotation mark ("
) character. This will be explained further in the next section. On another implementation of the C compiler which does not use ASCII code for the quotation mark character, the program needs to be modified to the use the correct code.
Here are some commands that demonstrate the quine:
$ echo -n 'main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);}' > quine.c $ cc quine.c $ ./a.out > out.txt $ diff quine.c out.txt $ ./a.out main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);}
The source code of this quine does not end with a newline. The -n
option of GNU echo ensures that the source code file is created without a terminating newline.
Close Look at the Classic Quine
Let us take a close look at how the quine introduced in the previous section works. Let us add some newlines in the source code of this quine for the sake of clarity.
main()
{
char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";
printf(s,34,s,34);
}
This is almost the same program presented in the previous section. Only a few newlines have been added to it to make the program easier to read.
We can see that the printf
call uses the string s
as the format string. The format string contains three conversion specifications: %c
, %s
, and %c
. The arguments for these conversions are: 34
, the string s
itself, and 34
once again. Note that 34
is the ASCII code for the quotation mark character ("
). With that in mind, let us now construct the output of the printf
call in a step-by-step manner.
The initial portion of the output consists of the format string from the beginning up to, but not including, the first conversion specification copied unchanged to the output stream. Here it is:
main(){char*s=
Then the first conversion specification %c
is processed, the corresponnding argument 34
is taken, and a quotation mark is printed like this:
"
Then the second conversion specification %s
is processed. The corresponding argument is the string s
itself, so the entire string is printed like this:
main(){char*s=%c%s%c;printf(s,34,s,34);}
Then the third conversion specification %c
is processed. The corresponding argument is 34
again, so once again a quotation mark is printed like this:
"
Finally, the rest of the format string is copied unchanged to produce the following output:
;printf(s,34,s,34);}
Here are all the five parts of the output presented next to each other:
main(){char*s=
"
main(){char*s=%c%s%c;printf(s,34,s,34);}
"
;printf(s,34,s,34);}
Writing them all out in a single line, we get this:
main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);}
This output matches the source code of the program thus confirming that our program is a quine.
Classic Quine With Terminating Newline
The source code of the classic quine presented above does not terminate with a newline. I found that a little bothersome because I am used to always terminating my source code with a single trailing newline at the end. So I decided to modify that quine a little to ensure that it always ends with a newline. This is the quine I arrived at:
main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34,10);}%c";printf(s,34,s,34,10);}
Compared to the quine in the previous sections, this one has an additional %c
at the end of the formal string and the integer 10
as the corresponding argument to ensure that the output ends with a newline. Here is a demonstration of this quine:
$ echo 'main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34,10);}%c";printf(s,34,s,34,10);}' > quine.c $ cc quine.c $ ./a.out > out.txt $ diff quine.c out.txt $ ./a.out main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34,10);}%c";printf(s,34,s,34,10);}
from Hacker News https://ift.tt/3GeZerZ
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.