discuss the different program errors that are likely to occur and how they shoul
ID: 3584739 • Letter: D
Question
discuss the different program errors that are likely to occur and how they should be handled within scriptsExplanation / Answer
This document lists the common C programming errors that the author sees time and time again. Solutions to the errors are also presented. Another great resource is the C FAQ. Gimpel Software also has a list of hard to detect C/C++ bugs that might be useful. 2. Beginner Errors These are errors that beginning C students often make. However, the professionals still sometimes make them too! 2.1 Forgetting to put a break in a switch statement Remember that C does not break out of a switch statement if a case is encountered. For example: int x = 2; switch(x) { case 2: printf("Two "); case 3: printf("Three "); } prints out: Two Three Put a break to break out of the switch: int x = 2; switch(x) { case 2: printf("Two "); break; case 3: printf("Three "); break; /* not necessary, but good if additional cases are added later */ } 2.2 Using = instead of == C's = operator is used exclusively for assignment and returns the value assigned. The == operator is used exclusively for comparison and returns an integer value (0 for false, not 0 for true). Because of these return values, the C compiler often does not flag an error when = is used when one really wanted an ==. For example: int x = 5; if ( x = 6 ) printf("x equals 6 "); This code prints out x equals 6! Why? The assignment inside the if sets x to 6 and returns the value 6 to the if. Since 6 is not 0, this is interpreted as true. One way to have the compiler find this type of error is to put any constants (or any r-value expressions) on the left side. Then if an = is used, it will be an error: if ( 6 = x) 2.3 scanf() errors There are two types of common scanf() errors: 2.3.1 Forgetting to put an ampersand (&) on arguments scanf() must have the address of the variable to store input into. This means that often the ampersand address operator is required to compute the addresses. Here's an example: int x; char * st = malloc(31); scanf("%d", &x); /* & required to pass address to scanf() */ scanf("%30s", st); /* NO & here, st itself points to variable! */ As the last line above shows, sometimes no ampersand is correct! 2.3.2 Using the wrong format for operand C compilers do not check that the correct format is used for arguments of a scanf() call. The most common errors are using the %f format for doubles (which must use the %lf format) and mixing up %c and %s for characters and strings. 2.4 Size of arrays Arrays in C always start at index 0. This means that an array of 10 integers defined as: int a[10]; has valid indices from 0 to 9 not 10! It is very common for students go one too far in an array. This can lead to unpredictable behavior of the program. 2.5 Integer division Unlike Pascal, C uses the / operator for both real and integer division. It is important to understand how C determines which it will do. If both operands are of an integal type, integer division is used, else real division is used. For example: double half = 1/2; This code sets half to 0 not 0.5! Why? Because 1 and 2 are integer constants. To fix this, change at least one of them to a real constant. double half = 1.0/2; If both operands are integer variables and real division is desired, cast one of the variables to double (or float). int x = 5, y = 2; double d = ((double) x)/y; 2.6 Loop errors In C, a loop repeats the very next statement after the loop statement. The code: int x = 5; while( x > 0 ); x--; is an infinite loop. Why? The semicolon after the while defines the statement to repeat as the null statement (which does nothing). Remove the semicolon and the loop works as expected. Another common loop error is to iterate one too many times or one too few. Check loop conditions carefully! 2.7 Not using prototypes Prototypes tell the compiler important features of a function: the return type and the parameters of the function. If no prototype is given, the compiler assumes that the function returns an int and can take any number of parameters of any type. One important reason to use prototypes is to let the compiler check for errors in the argument lists of function calls. However, a prototype must be used if the function does not return an int. For example, the sqrt() function returns a double, not an int. The following code: double x = sqrt(2); will not work correctly if a prototype: double sqrt(double); does not appear above it. Why? Without a prototype, the C compiler assumes that sqrt() returns an int. Since the returned value is stored in a double variable, the compiler inserts code to convert the value to a double. This conversion is not needed and will result in the wrong value. The solution to this problem is to include the correct C header file that contains the sqrt() prototype, math.h. For functions you write, you must either place the prototype at the top of the source file or create a header file and include it. 2.8 Not initializing pointers Anytime you use a pointer, you should be able to answer the question: What variable does this point to? If you can not answer this question, it is likely it doesn't point to any variable. This type of error will often result in a Segmentation fault/coredump error on UNIX/Linux or a general protection fault under Windows. (Under good old DOS (ugh!), anything could happen!) Here's an example of this type of error. #include int main() { char * st; /* defines a pointer to a char or char array */ strcpy(st, "abc"); /* what char array does st point to?? */ return 0; } How to do this correctly? Either use an array or dynamically allocate an array. #include int main() { char st[20]; /* defines an char array */ strcpy(st, "abc"); /* st points to char array */ return 0; } or #include #include int main() { char *st = malloc(20); /* st points to allocated array*/ strcpy(st, "abc"); /* st points to char array */ free(st); /* don't forget to deallocate when done! */ return 0; } Actually, the first solution is much preferred for what this code does. Why? Dynamical allocation should only be used when it is required. It is slower and more error prone than just defining a normal array. 3. String Errors 3.1 Confusing character and string constants C considers character and string constants as very different things. Character constants are enclosed in single quotes and string constants are enclosed in double quotes. String constants act as a pointer to the actually string. Consider the following code: char ch = 'A'; /* correct */ char ch = "A"; /* error */ The second line assigns the character variable ch to the address of a string constant. This should generate a compiler error. The same should happen if a string pointer is assigned to a character constant: const char * st = "A"; /* correct */ const char * st = 'A'; /* error */ 3.2 Comparing strings with == Never use the == operator to compare the value of strings! Strings are char arrays. The name of a char array acts like a pointer to the string (just like other types of arrays in C). So what? Consider the following code: char st1[] = "abc"; char st2[] = "abc"; if ( st1 == st2 ) printf("Yes"); else printf("No"); This code prints out No. Why? Because the == operator is comparing the pointer values of st1 and st2, not the data pointed to by them. The correct way to compare string values is to use the strcmp() library function. (Be sure to include string.h) If the if statement above is replaced with the following: if ( strcmp(st1,st2) == 0 ) printf("Yes"); else printf("No"); the code will print out Yes. For similar reasons, don't use the other relational operators (, etc.) with strings either. Use strcmp() here too.Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.