|
In this list I'll cover 12 common pitfalls that are made in C. The
checklist is meant as a tool for beginners.
- Remember to start and end comments correctly.
Comment begin: /*
Comment end: */
- The assignment operator '=' is often mistaken for the test operator
'=='. This mistake is easy to make since many other programming
languages use '=' as a test operator. The compiler may not discover this
type of error since the assignment has a value and therefore is legal in
an expression. An example is:
if (number = 9)
number = 0;
'number' is assigned the value 0 since the 'number = 9' assignment always
returns a true value.
- Errors with assignments in statements. Missing brackets around
assignments causes errors that the compiler wont be able to find. Example:
while (ch = getchar() != EOF)
'ch' will here be assigned the value 1 for TRUE until 'getchar()' returns
EOF, where 'ch' is assigned the value 0 for FALSE. The correct statement:
while ((ch = getchar()) != EOF)
- Errors with arrays. In C the lowest array-index is zero, i.e.
the following declaration:
int myArray[10];
sets up 10 elements myArray[0], myArray[1], ..., myArray[9]. Example:
for (i=0; i <= 10; i++)
myArray[i] = i;
Since C doesn't have runtime-checks of array boundaries, this example will
cause the variable myArray[10] to be assigned a value. But since
myArray[10] hasn't been declared another variable will be overwritten.
[...If there is another variable in memory right after the array. Lack of
bound checking is the cause of many security holes in networking software.
Ed].
- Remember brackets when calling a function without parameters.
Example:
x = square; /* incorrect */
and
x = square(); /* correct */
Note: Depending on what compiler you have you will get a compiler error
from the line above.
- Errors by transferring a pointer to a function. If the function
'convert' is declared as
void convert(int *px);
where the parameter is a pointer to an integer, the function has to be
called with a pointer as parameter. Example:
int result;
convert(&result);
The typical error is caused by omission of the address operator '&'
- Remember to declare functions. If functions returns other
values than the 'int' type, they have to be declared before they are
called. Example:
long a;
a = getlong();
In this case 'a' is assigned an 'int' instead of a 'long'. In order to be
correct the function has to be declared like this (also called
prototyped):
/* The void is not necessary, but good practice */
long getlong(void);
long a;
could also be declared like this [confusing style though. Ed]:
long a, getlong(void);
- Remember 'break' in the 'switch' construct. If you forget a
'break', the program will continue until it meets another 'break' or the
end of the 'switch' block has been reached. Example:
switch (weekday)
{
case MONDAY : printf("Start a new week");
case TUESDAY: /* no break here */
case FRIDAY :
workday++;
break;
default: weekday++;
}
If you start with MONDAY you will also execute the TUESDAY and FRIDAY code
because there is no break until after FRIDAY, which means that default
wont be executed unless weekday is different from MONDAY, TUESDAY or
FRIDAY.
If there are statements executed with several entrances like in the
example above, and break is left out on purpose, it should be commented.
- Use of side effects in expressions. The use of side effects in
expressions can cause unpredictable programs. Example:
a[n] = n++;
is equivalent either to:
a[n] = n;
n = n + 1;
or to:
a[n + 1] = n;
n = n + 1;
Which case holds depends on the compiler.
- Errors with type conversions. Type conversion of a 'char' to an
'int' or a right shift of an 'int' can be done with or without a 'sign
extension'. [Which happens depends on how the compiler is implemented. Ed]
- Remember brackets with pointers and increment/decrement
operators. Example:
char line[80];
*lp = line;
ch = *lp++; /* the same as *(lp++) */
In this example 'ch' is assigned what 'lp' is pointing at after which lp
is incremented.
ch = (*lp)++;
In this example 'ch' is assigned what 'lp' is pointing at, but in this
case it's the value that 'lp' is pointing at that's incremented.
- Watch out that you don't confuse the logical operators (&&, ||)
with the bit operators (&, |).
This article is based on material collected by Finn Overgaard Hansen DTI
1993.
|
|