Today's Code Snippet comes from [Name blanked out to protect the innocent - Hereafter referred to as Mr. X.]. Mr X is a programmer who works on proprietary embedded systems which means that often what is considered by many to be "stdlib" functions aren't available and one has to first write the utilities that one needs. This, of course, allows for excellent possibility of spectacular results...

Mr X. writes, "I was recently required to port some code (originally written by a third-party) to a slightly different architecture, it was to be a journey; I laughed, I cried, I wanted to strangle someone... but hopefully I can summarize. I give you the atoi implementation from hell."

long atoi(char *s)
{
       char *p;
       int l;
       long m=1, t=0;  /* init some vars */
       bool negative = FALSE;

       /* check to see if its negative */
       if(*s == '-') {
               negative = TRUE;
               s++;
       }
       /* not negative is it a number */
       else if(s[0] < '0' || s[0] > '9')
       {
           return 0;
       }

       l = strlen(s);

       p = s + l;                           /* start from end of string */
       /* for each character in the string */
       do {
               p--;                         /* work backwards */
               t += m * (*p - '0');         /* add new value to
total, multiplying by current multiplier (1, 10, 100 etc.) */
               m = (m << 3) + (m << 1);     /* multiply multiplier by
10 (fast m * 10) */
               l--;                         /* decrement the count */
       } while(l);
       if(negative)
               t = -t;                      /* negate if we had a -
at the beginning */
       return t;                            /* return the total */
}

Demonstration is always the key to getting a point across, so here are a few examples in truth-table form.

atoi("2z") == 94
atoi("-z") == -74 // at least it got the sign right
atoi(NULL) == [memory violation] // usually triggering a hardware interrupt
In this implementation of atoi you need to be totally certain what you give the function has a valid integer representation (and nothing extra!) or you're hosed. To put it plainly, you need to know the result before attempting to get the result. My favorite line is the one with the comment, (fast m * 10). Beautiful.

Would you believe it gets worse? Or perhaps... better? This is just one of many "stdlib" functions implemented in this file which also contains a bunch of "math.h" functions...

  • sin & cos (use a look-up table which is not so bad but), due to poor range snapping, achieve an accuracy of around 2 degrees including a persistent phase shift of up to 1 degree whose sign depends on the segment the original input should have fallen in.
  • tan is implemented as the simple sin/cos macro so it has an even higher error rate and, again, due to phase swapping the resulting shift is multiplied - should probably just call it rand because...
  • rand is biased towards zero (the basis is not linear).
  • sqrt uses a fixed loop count (rather than a target epsilon) to terminate the convergence, resulting in wildly inaccurate values as the input increases. e.g. sqrt(10000) == 1251.5

All of the above is from just 1 file - there were 8 other files in this library.

Morals of the story (aside from the usual lessons of witnessing ineptitude)

1. "stdlib" type libraries, that most programming languages come bundled with, which are generally taken for granted by the programmers using the language, are not exempt of defects - and in some cases, they can be the source of the worst crimes one might see in said language.

2. Only trust a code comment as far as you trust the person who wrote it. The 'atoi' implementation shown here was adorned with the comment "ANSI compatible"... I cannot even begin to express my bewilderment at how anybody capable of cobbling together the C-code shown could possibly believe they had produced something on-par with the standard 'atoi'.