1 <!-- subject: Prime numbers less than 100 -->
2 <!-- date: 2010-12-12 18:30:59 -->
3 <!-- tags: c, primes, brain-teaser -->
4 <!-- categories: Articles, Misc, Techblog -->
6 <p>Anyone working in a major company must have been hit by some
7 ‘funny’ mail from a coworker that helps everyone gets through the
8 day. No different at my office — at one point all
9 engineers have been challenged to write the shortest code in
10 C that prints all prime numbers (and only prime numbers) less
11 than a hundred each on separate line.
13 <p>This is an interesting brain-teaser so posting it here so others
14 may choose to think about it while
<a
15 href=
"http://xkcd.com/303/">their code’s compiling
</a>.
17 <p>Of course, a ‘C program’ needs not to be taken too seriously — depending on
18 not too far fetched undefined behaviours of given implementation is all right
19 (but please do not use
<code>system
</code> or
<code>exec
</code> family of calls;
20 not that I can see how that would help).
22 <p>By the way, if you’re interested in how this challenge looks solved in Rust,
23 I’ve
<a href=
"/2021/prime-numbers-less-than-a-hundred-in-rust/">described
30 <p>I have managed to came up with two
61-character (this excludes new
31 line at the end of the file) solutions — one uses two loops
32 and the other only one:
34 <pre>main(i,j){for(;j=i++
<99;)for(;++j
<i||printf(
"%d\n",i),i%j;);}
</pre>
36 main(j,i){for(i=
2;i%++j||(i
>j||printf(
"%d\n",i),j=i++
<99););}
</pre>
38 <p>I have used a comma operator to print the prime number
39 but
<a href=
"#comm1573336">Wasacz solution
</a> shown that it is not
40 necessary and thus a
60-character solution can be created:
42 <pre>main(i,j){for(;j=++i
<99;j
<i||printf(
"%d\n",i))for(;i%++j;);}
</pre>
46 <p>Let’s look at the code to see how much does it bend the
47 C language rules. I will look through some of the surprising
48 constructs and try to clarify them. Some of the comments are of
49 historic importance only but nonetheless may be interested for
50 a C programmer curious about ins and outs of the
53 <p><b>Implicit return type
</b>. Starting from the beginning, the
54 <code>main
</code> function has no return type specified. That is
55 actually quite all right since C89 defaults function’s return type to
58 <p><b>Old function prototype
</b>. This is not the only ‘problem’ with
59 the function though.
<code>main
</code>’s prototype lacks also argument
60 types. This is also a perfectly valid C syntax. In original design
61 types were not part of function declaration and, not to break old code,
62 this (otherwise deprecated syntax) remained in C89. The old function
63 definition looks as follows:
66 <i>rettype
</i> foo(
<i>arg1
</i>,
<i>arg2
</i>)
67 <i>type1
</i> <i>arg1
</i>;
68 <i>type2
</i> <i>arg2
</i>;
73 <p>Programmers were responsible for guaranteeing correct function
74 invocation which lead to many hard to find bugs and thus
75 a
<code>sparse
</code> tool was created which, among other things,
76 checked whether all function invocations match function
79 <p>Digging more in this topic, when C89 standard was published not all
80 compilers were fully compatible with it (in particular, not all
81 supported the new function prototypes), which lead programmers to the
82 use of a macro that let them omit function prototype when compiling
83 with old compiler, ie.:
92 <i>rettype
</i> foo P((
<i>type1
</i>,
<i>type2
</i>));
</pre>
94 <p>What is quite important to note here is that in C empty arguments
95 list in function declaration does not mean that the function take no
96 argument (which is true in C++). It means function take unspecified
97 number of arguments. To declare function with no arguments one needs
98 to use
<code>void
</code> keyword, ie.:
<code>int foo(void)
</code>.
100 <p><b>Implicit type
</b>. So, what
<em>is
</em> the type of
101 <code>main
</code> arguments? There was none specified anywhere. This
102 is, yet again, quite all right since C89 defaults to
<code>int
</code>.
103 Generally, anything that has been declared but has no type specified is
104 of type
<code>int
</code>. For example
<code>static i;
</code> is the
105 same thing as
<code>static int i;
</code>.
107 <p><b>Incorrect argument type
</b>. This brings us to the next issue.
108 The two
<code>main
</code> function prototypes defined by the standard
112 int main(int, char **);
113 int main(void);
</pre>
115 <p>This stays in conflict with our second argument being (implicitly)
116 defined as having type
<code>int
</code>. This is the first place were
117 undefined behaviour is introduced. Theoretically, undefined behaviour
118 can lead to anything, including daemons coming out of your nose, but
119 because in most (for some definitions of ‘most’) implementations
120 <code>sizeof(int)
</code> is no smaller than
<code>sizeof(char *)
</code>,
121 passing convention for the two type is compatible and
<code>int
</code> has
122 no trap representations, we are in the clear.
124 <p><b><code>i
</code>’s initialisation
</b>. Looking carefully at the
125 code one notices that
<code>i
</code> is never initialised and instead it
126 uses the value passed as first argument to
<code>main
</code> as its
127 initial value. This reveals a quite interesting bug: if one calls the
128 program with some arguments, it will skip initial prime numbers.
130 <p>What I find more fascinating though is situation where
131 <code>main
</code>’s first argument is zero (which standard permits). In
132 this situation
<code>j
</code> will overflow (which is undefined
133 behaviour for signed integers) and the second loop will finish
134 when
<code>j
</code> reaches
<code>-
1</code>. This is also a situation
135 where
<code>b/a
</code> will yield undesired true value hence it is
136 better to use
<code>j
<i
</code> comparison.
138 <p><b>Implicit declaration
</b>. Obviously, to output the number we’ve
139 used
<code>printf
</code> function. This is a straight-forward approach, yet we
140 are missing its declaration. And yet again, this is quite all right from C89’s
141 point of view. If function declaration is missing an implicit declaration based
142 on types of passed arguments with
<code>int
</code> as a return type is assumed.
144 <p>Let’s stay here for a second because this is a good
145 opportunity to yet again remind everybody not to cast result of
146 <code>malloc
</code> function. Consider the following code:
150 int *p = (int *)malloc(sizeof *p); /* incorrect */
154 <p>Some compilers will (rightly) accept such code with no complains
155 even though one forgot to include the
<code>stdlib.h
</code> header file.
156 Because of the implicit function declaration rule the compiler will
157 assume a
<code>int malloc(size_t)
</code> prototype and then (because
158 of cast operator) will obediently convert
<code>int
</code> into
159 a pointer to
<code>int
</code>. Without the cast, compiler will have
160 to complain about implicit conversion from
<code>int
</code> to pointer
161 type reminding about the header file:
165 int *p = malloc(sizeof *p); /* correct */
169 <p><b>Lack of return
</b>. The last issue with the prime number
170 printing code is the lack of return statement. C99 specifies that
171 ‘reaching the
<code>}
</code> that terminates the
<code>main
</code> function
172 returns a value of zero.’ One cannot hide behind C99 though since the
173 code uses various C89 only ‘features’ (implicit type, implicit
174 function declaration, etc). Yes, this is another undefined behaviour
177 <p>Hope you have all enjoyed this little brain-teaser and maybe even
178 got some interesting information about the C language from this
182 <!-- date: 2010-12-12 21:50:52 -->
183 <!-- nick: mina86 -->
184 <!-- nick_url: http://mina86.com -->
186 <p>72 actually since
"%d " needs to be
"%d\n".
190 <li>Is
<code>if
</code> the only control structure that can be used?
191 <li>Would pre-incrementation (as opposed to post-incrementation) change anything?
192 <li>Do you need to compare with
100?
196 <!-- date: 2010-12-13 10:16:10 -->
197 <!-- nick: Wasacz -->
198 <!-- nick_url: http://blog.wasacz.net -->
200 <p>Hints applied: https://ideone.com/iHe9v
205 <!-- date: 2010-12-13 11:19:00 -->
206 <!-- nick: mina86 -->
207 <!-- nick_url: http://mina86.com -->
209 <p>Yep, that’s it. :) When I get back from work I’ll also post a version with one loop as it may be interesting.
212 <!-- date: 2010-12-13 11:24:15 -->
213 <!-- nick: mina86 -->
214 <!-- nick_url: http://mina86.com -->
216 <p>Ha! Actually, modifying your code I got down to
60. ;) Hint: Does you need the literal
<code>1</code> value in the source code?
219 <!-- date: 2010-12-13 11:54:38 -->
220 <!-- nick: Wasacz -->
221 <!-- nick_url: http://blog.wasacz.net -->
223 <p>Wow ;) https://ideone.com/LqjjH
226 <!-- date: 2010-12-14 08:42:44 -->
228 <!-- nick_url: http://rozie.blox.pl/ -->
230 <p>Perlgolfa widziałem, ale Cgolf?
8-o
<br />
234 <!-- date: 2010-12-29 22:40:30 -->
235 <!-- nick: mina86 -->
236 <!-- nick_url: http://mina86.com -->
238 <p>Still, you can optimise it a bit (
85):
240 <pre>main(n,j){long long x=
0x3986291891100;for(puts(
"2");x/=
4;printf(
"%d\n",n+=x%
4*
2+
2));}
</pre>