Previous Section Table of Contents Next Section

B-Blunder

B.variable

An easy and common mistake is using the wrong variable name. For example, the author meant to write


i = 5;


but instead wrote


j = 5;


In many languages, this generates an error unless j is defined and is the same type as i, but the existence of two variables of the same type and similar names can be the cause of the B.variable error (because the programmer is thinking about both variables), so this is more common than you might expect. Often, when first typing in code, there will be typos. For example, your finger might slip off the I key and hit the adjacent key to wind up with:


io = 5;


Whether this is caught quickly might depend on how the language specifies that undeclared variables should be treated.

One source of B.variable errors is cutting-and-pasting similar code. For example, in code that looks like the following


// adjust the endpoint of the line

x1 = transform (x1, x2, current_transform);

y1 = transform (y1, x2, current_transform);


the second line was likely copied from the first and each occurrence of x was changed to y by hand, with one of them being missed, which generates legal but likely incorrect code.

Anywhere a variable is used, it's possible to use the wrong one-on the left or right side of an assignment, as an argument to a function, as a return value from a function, and so on. One situation that arises is switching two variables in the parameters to a function, which passes unnoticed by the compiler as long as they are the same type. That is, calling:


draw_dot(y, x)


instead of:


draw_dot(x, y)


Knuth calls this class of errors Mismatches, but I won't define a separate category for them. If your code has two functions with similar names (or even dissimilar names), it might also use the wrong function name instead of the wrong variable name.

B.expression

The B.expression is a more general form of the previous category, B.variable. A variable on its own is an "expression," but the case of just using the wrong variable name is so common that it was separated. B.expression covers other cases in which expressions are incorrect not because of the algorithm being wrong, but because of a momentary cramp in the programmer's brain.

The most basic of these errors is when the code uses the wrong operator


a = a + 2;


instead of:


a = a * 2;


Given that expressions can be arbitrarily complex, there is an arbitrary opportunity to make mistakes. One place that bad expressions may appear is in an if statement:


if ((count < min) && (count > max))


This example is almost certainly not what the author intended (assuming min is less than max, the expression will never be true). At times, it is not clear if the mistake is a typo or simply a bad algorithm. In these cases, a nearby comment might help differentiate:


// Make sure a is less than 100

if (a > 100)


That code is likely a typo, but:


// If these are equal, k is divisible by five

if (((k-1) / 5) == (k/5))


is more likely to be an A.logic error because the comment matches the code (but both are incorrect). In general, if the mistake is simple, only occurs in one place, and is inconsistent with the rest of the program, it probably belongs in B.expression.

The logical "and" and "or" operators are common areas where the wrong operator is used in an expression, usually by using and instead of or or vice versa. For example, the example above might have been intended to be as follows:


if ((count < min) || (count > max))

    // code to handle an invalid count


Conversely, the && might have been correct and the > and < might have been reversed (another error that occurs often)- the intent was to write the following:


if ((count > min) && (count < max))

    // code to handle a valid count


In the first case, the if() was checking for a count that was out of range. In the second case, it was checking for a count that was within the proper range. (Although it is more likely in that case that the proper comparison operators would have been >= and <= instead of > and <.)

In the end, it does not matter why the code is wrong; it has to be fixed. Still, a typo is arguably more likely to be a single localized mistake (unless it was duplicated elsewhere through cut-and-paste) while a logical error might indicate more fundamental problems.

B.language

Some languages have syntax features that can lead to improper expressions. This is what Knuth calls Language Lossage. For example, expressions that depend on the precedence of operators can be interpreted in a non-intuitive way. In C, the following statement that uses &, the boolean "and" function


if ( i & 1 == 0 )


is parsed by the compiler as:


if ( i & (1 == 0) )


This is unlikely to be the author's intention.

Another example is the following C fragment:


if (i == 5); {

    i = 0;

}


This fragment is syntactically correct, but the semicolon (;) after the if() is interpreted as the entire if() body, which means that the i = 0; statement always executes. Other cases of this in C include neglecting to include a break after a case in a switch statement, and using = instead of == in a comparison. If that didn't make sense to you, don't worry-none of the bugs in this book depend on such quirks of the language.

    Previous Section Table of Contents Next Section