“Q: I know Google has a policy where every new employee has to get checked out on languages before they’re allowed to check code in. Which means you had to get checked out on C [which you co-created].
Thompson: Yeah, I haven’t been. Q: You haven’t been! You’re not allowed to check in code?
Thompson: I’m not allowed to check in code, no… I just haven’t done it. I’ve so far found no need to.“ [Coders at Work]
The Reg is right; It would be madness for Google to test Ken Thompson on his C programming skills. The Reg is also wrong; It is not because he co-designed the C language. Designing a car doesn’t necessarily make you a good driver. At my own level, I have designed several languages. I wrote test code in those languages but I would not hire myself to code in those languages.
Google should not test Ken Thompson on his C coding skills because it is insulting to one of the icons of the computer industry. Because he is Ken Thompson.
Ok, it was 1 am as I switched off the TV and only than I remembered I had to fix the flat tire on my kid’s bike. No biggy, this would only take 20 minutes, so I get my gear and start to work. Bummer, I need to take out the wheel, the leak is too small to hear. Ok, maybe 30 minutes, no worries. So I disengage the hub dynamo, noting the plus wire has a white stripe on it. I find the hole, fix it, reassemble the tire, and in my head I am already in my bed, in just 2 more minutes everything is properly reaffixed. I test the light as a matter of double compulsion. After all I am both a coder as well as a caring father. The light refuses to work. Maybe the connector is dirty. I start debugging, working my way up from the hub to the lamp. Twenty minutes later, I have the whole thing off the bike, stripped naked on the table and I take my multimeter to it. I curse these digital IC controlled lights. It used to be so simple. Just one wire connecting a dynamo and a bulb. (Or spit into the carbide lamp.) Whoever asked for a “wunderlamp”? After an other five minutes, I find out the bulb looks ok, but the meter tells me it’s broken. Curses! Why did my kid not tell me her light needed fixing? I would have checked the bulb first thing. Because of the flat tire I started debugging at the wrong end. Because I assumed the light was working before, I assumed the connector was the most probable thing to be at fault. That good all MOAFU called assumption. It is bad enough that I have to endure bad error propagation at work, but from my own blood?
It’s not often that a coder can blame the design, actually I know of only one case: (hint, click the image) Image from xkcd. (Thanks John!) Warning clicking the link can cause serious RSI from clicking Next>.
Using malloc() and free() necessitates care; a lot of care. In fact, I can not remember seeing any non trivial C program, that would not have an extra memory management layer. Often a double linked list was involved and atexit() reporting of non free()ed memory. At the very least some simple reporting was going on usually redefining malloc() in terms of mall##oc(). I recently used the latter construct, to show off my superb arcane knowledge of the C pre processor, when I was met with skepticism; What was wrong with the LOC below?
To demonstrate (how little this PFY knew and) how cpp was going to balk at the recursive definition, I typed it in and, low and behold, the compiler accepted it and generated the right code. All I could do was grin. Of cause I had always realized that not adding a token to the symbol table before the whole definition was parsed would be better, but compilers just never did. Who changed this when? And would this open the door to recursive macro’s, does the pre processor do a multipass? So I ran the two snippets below through gcc-E to expand A(4).
A(4) ∴ A(4 +1 +3)
A(4) ∴ (4 +1 +3)
As you can see, there is some lazy expantion going on. If we RTFM, it shows that: “Each macro is expanded when it appears in the definition of the other macro, but not when it indirectly appears in its own definition.“ Ok, I’ve learned never to trust things to stay the same, again.
Clock or modular arithmetic is hard. Take a look at the two code snippets below. Both seem reasonable integer comparison functions modeled after strcmp(). However, the left one contains an overflow bug.
I have thirty odd years of programming experience, yet I had to be pointed out the bug. The left snippet looks obviously wrong to me, now. It’s like claiming that we go back in time if the short hand of a clock moves more than 6 hours. Ridiculous. (And, no, intermediate casting to long won’t help.) Just try a few extreme cases using INT_MIN, for example. Clock arithmetic is hard because if the modulus is sufficiently large we tend to ignore it. So, if you have to go against the first directive, if you don’t trust the -O4 option, or if you just have to show off how brilliant you are, use something like the C code on the right. It won’t bring you much, but at least it does not contain an overflow bug. Though it might contain an other one, or show a incompatibility in your compiler. But that is left as an exercise to the reader.
Randomness is really not compatible with the human mind. We see order in everything. Only homogeneous distributions feel random to humans. If you role a dice three times and it comes up sixes, you (and me) either suspect the dice is weighted or the next throw, for sure, is going to be not-six. Don’t deny it, random must be “fair.” Look at the dots in the scatter plots above, which is schemed and which is random? Sometimes a whole paper is needed to convince scientist that distributions are just random and that there is no underlaying scheme. Look for example at [Clustering of the Cosmic Ray Ages of Stone Meteorites] (Andrew S. Tanenbaum).
To accommodate human feelings some form of control over the randomness is needed. “The way to handle controlled randomness is actually pretty simple. It’s commonly called a shuffle bag.” (Sean McArthur) [A Less-Random Generator] Almost all successful games use random control like that.
To me, it becomes interesting when I have to wonder: “Is it a joke, or not?” Look at the code below and tell me, given that this is part of the MINIX POSIX compliance test set, is this juste pour rire?
I usually burst out singing: “Those who try to tangle with my daring do, end up at the angle that herring do.“ (Danny Kaye) [Outfox the Fox] Never try to outfox the compiler. Take a look at what gcc generates to divide an integer by 13 in x64 and PowerPC assembler (approximately):
It is not uncommon for a divide instruction to take more than four times as long as a multiplication. Shift and register loading typically are up to fifty times faster. Above (speed) optimization is a simplified (i.e., unsigned) example. It does not take into account that floating point divides can be executed in parallel with integer code, it does not take into account the instructions in the CPU’s pipeline, it does not take into account surrounding code, it does not take into account MMX/SSE instructions, etc. For the curious, there is a excellent blog post on the why and how of multiply/shift-back. Remember, the rule is: you will never outfox the GNU-fox or any other optimizing fox. But if you have to outfox the fox look for inspiration first.
Are you a lead developer? Do you feel commercially trapped? Would you like your own company for your brainchild? Are you too risk averse to start it? Change the rules! Start by visiting 4F Invest. You'll find it interesting.