[SJF Logo]
Steve Friedl's Weblog

February 21, 2003
Code bloat, C style

Today I was reviewing some C code and found this hideous piece of trash that showed just how badly off the rails a program can go if somebody doesn't know their friendly-neighborhood C library. Let's look at this in some detail:

 1 /*
 2  * n_int()
 3  *
 4  * Generic n = nint(x) function, where 'x' is a double and 'n' is
 5  * an integer.  'n' is the whole number portion of 'x'.  Example:
 6  * if x = 2.3456, then n = 2. This code is brute force, but should
 7  * work on most C compilers.  Additionally, n_int() is only called
 8  * a couple of times in the program and this should not have any
 9  * noticable performance impact.
10  */
11 int n_int(double x)
12 {
13         char    s[128];
14         char   *p;
15         int     n;
16
17         /*
18          * Convert 'x' to character representation.
19          */
20         sprintf(s, "%10.10lf", x);
21 
22         /*
23          * Find the decimal point (or end of string if no '.').
24          */
25         p = s;
26         while (*p != '.' && *p != '\0')
27                 p++;
28 
29         /*
30          * Truncate string at decimal point and convert
31          * the integer portion of the number.
32          */
33         *p = '\0';
34         sscanf(s, "%d", &n);
35 
36         return (n);
37 }
The idea is to truncate the fractional part of the integer, many large steps are being taken that don't need to be. Lines 22-33 look for the decimal point -if any - and truncate it, but this is what the strchr() library function is for.
if ( (p = strchr(s, '.')) != 0 )
    *p = '\0';
Line 33 uses the overkill sscanf to convert a string to an integer, but when the atoi() function is available, it should be used instead. But since atoi stops once it finds a non-digit anyway, there is no need to truncate the decimal point - this obviates a whole step. Duh.

Those versed in the math library will certainly point to the floor() function, which returns the greatest integer not larger than the given floating point value, and this has great promise. Even accounting specially for negative numbers, the code is much simpler:

int n_int(double x)
{
int n = (int) floor(x);

     if ( n < 0 ) n++;

     return n;
}
Are we done? No, not quite. Since the goal of this function is simply to perform integral truncation towards zero, why not let the compiler do it for you intrinsicly? This is the usual behavior for float-to-int conversion, so our function now becomes:
int n_int(double x)
{
    return (int) x;
}
Sigh.

Posted by Steve at February 21, 2003 05:25 PM | TrackBack

Comments

Really amusing. :-)

Posted by: Mosse on June 15, 2003 06:19 AM
Post a comment
Name:


Email Address:


URL:


Comments:


Remember info?