15 Common C Language Traps in Embedded Development

Scan and follow to learn embedded systems together, grow together.

C is a very popular programming language due to its simplicity and wide application across various fields. However, due to the characteristics of C, it is also prone to certain errors and traps that can lead to program crashes, data loss, or security vulnerabilities. This article will introduce 15 common traps in C programming and provide corresponding solutions.

At the end, there is an interview question, and everyone is welcome to discuss and learn.

1. Operator Precedence

C has many operators, such as addition, subtraction, multiplication, division, and logical operators. In expressions, different operators have different precedence levels, and if this is not taken into account, errors can occur. For example:

int a = 5, b = 3;
int c = a++ * --b; // a = 6, b = 2 and c = 10.

In this example, ++ and — have higher precedence than *, so a and –b are executed first, followed by the multiplication operation. If the above code is written like this, the result will be completely different:

int a = 5, b = 3;
int c = ++a * b--; // Now a=6, b=2, c=18

Here, ++a and b– are executed first, followed by the multiplication operation.

Solution: Understand the precedence of each operator correctly and use parentheses to clarify the order of operations in expressions.

2. Case Sensitivity

In C, variable names and function names are case-sensitive. That is, myVar and MyVar are two different variable names. This can easily lead to confusion and errors, for example:

int MyVar = 5;
int myvar = 3;
printf("%d\n", MyVar + myvar); // Outputs 8

Solution: Maintain consistency by using a unified naming convention to avoid confusion.

3. Array Out of Bounds

Array out of bounds refers to accessing an array beyond its boundary. This can lead to program crashes or data corruption. For example:

int arr[3] = {1, 2, 3};
int x = arr[3]; // Out of bounds access

Solution: Be aware of the boundary limits of arrays and avoid accessing elements beyond the range.

4. Integer Overflow

In C, integer overflow is a common issue. When an integer exceeds its representable range, its value will wrap around, i.e., it will change from the maximum value to the minimum value, or vice versa. For example:

unsigned char x = 255;
x += 1; // Now x's value is 0

Solution: Use appropriate data types to avoid exceeding their representable ranges.

5. Pointer Issues

Pointers are an important concept in C, but they can also lead to errors. For example, if a pointer is assigned NULL and is used without checking, it can produce strange results:

int *p = NULL;
*p = 5; // Error: Accessing a null pointer

Solution: Check if a pointer is NULL before using it.

6. Random Number Seed

In C, when using the rand() function to generate random numbers, a seed must first be set using the srand() function. If no seed is set, the same sequence of random numbers will be generated each time the program runs. For example:

for (int i = 0; i < 10; i++) {
    printf("%d ", rand()); // Outputs the same number sequence
}

If srand() is not used to set the seed, the same sequence of random numbers will be generated each time the program runs because the rand() function generates an initial seed based on the current time and uses it to generate pseudo-random numbers. If srand() is not used to change the seed, the same seed will be used, resulting in the same random number sequence. Therefore, it is generally recommended to set a new seed each time the program runs, such as using the time() function to get the current time as the seed value to ensure that the generated random number sequence is sufficiently random.

Solution: Use the time() function in the program to obtain a random seed.

srand(time(NULL));

7. String Handling

In C, a string is an array of characters terminated by a null character ‘\0’. However, if you accidentally forget to add the null character or access the string out of bounds, problems can arise. For example:

char str[10] = "hello";
str[5] = 'w'; // Error: No null character added
printf("%s\n", str); // Outputs "hellow"

In C, strings are character arrays terminated by a null character (‘\0’). When declaring a character array, the array length must be one more than the actual number of characters stored to accommodate the final null character. In this example, the length of the character array str is 10, storing 5 characters “hello” and 1 null character (‘\0’). When we assign the 6th character to ‘w’, although the character ‘w’ exists in the array, there is no corresponding null character following it, so the character array is not a valid string.

Since the printf() function uses the null character (‘\0’) to determine the end of the string, when the string does not contain a null character (‘\0’), printf() will continue to output any content immediately following its memory location until it finds a null character (if it cannot find one, it will lead to undefined behavior). In this example, the memory area immediately following the character array str may contain other data, so printf() may output something we do not want to see. To fix this issue, a null character (‘\0’) should be manually added at the end after modifying the string, making the array a valid C-style string:

char str[10] = "hello";
str[5] = 'w';
str[6] = '\0';
printf("%s\n", str);

The output will be “hello” followed by a space and “w”.

8. Loop Conditions

When writing loops, if the condition is incorrect, it may lead to infinite loops or the loop body not executing at all. For example:

int i = 0;
while (i < 10) {
    printf("%d ", i);
}

In this loop, the condition i<10 is always true, so the loop will continue indefinitely.

Solution: Carefully check the loop condition to ensure it can terminate the loop correctly.

9. Variable Scope

Variables in C have different scopes, and if this concept is not understood, errors can easily occur. For example:

int x = 1;
if (x == 1) {
    int y = 2;
}
printf("%d\n", y); // Error: y's scope is within the if statement block

Solution: Understand variable scope and ensure variables are defined and used in the correct locations.

10. Type Conversion

In C, type conversion is a common operation but can also lead to errors. For example:

int a = 5;
double b = 2.0;
printf("%f\n", a / b); // Outputs incorrect result

In this code, a is an integer variable, and b is a double variable. When performing division, the compiler will perform implicit type conversion, converting the integer variable a to a double before performing the division, resulting in a double result. Since the printf() function uses the %f format specifier to output floating-point numbers (including float and double types), even if the result is an integer, it will be interpreted as a floating-point number and output in decimal form.

However, in this case, the output result may differ from the expected result. According to the rules of integer division in C, the result of dividing two integers is also an integer, and the decimal part will be truncated. Therefore, in this example, the result of 5/2 should be 2 instead of 2.5. Thus, the correct output format should use %f to output a floating-point number:

int a = 5;
double b = 2.0;
printf("%f\n", (double)a / b);

Here, the integer variable a is explicitly converted to double, ensuring that the division of an integer by a floating-point number does not result in implicit type conversion, yielding a double result that can be correctly output by the %f format specifier.

11. Function Calls

In C, function calls are an important operation, but they can also lead to issues. For example, when calling a function, the types and number of parameters must match those in the function declaration, or a compilation error will occur. For example:

int add(int a, int b) {
    return a + b;
}
printf("%d\n", add(1, 2, 3)); // Error: Incorrect number of parameters

Solution: Ensure that the types and number of parameters in the function call match those in the function declaration.

12. Struct Access

In C, a struct is a custom data type composed of multiple member variables. To access struct members, the ‘.’ operator is used. However, if the struct pointer is NULL or the struct member does not exist, errors can occur. For example:

struct Person {
    char name[10];
    int age;
};
struct Person *p = NULL;
printf("%s\n", p->name); // Error: Accessing null pointer

Solution: Check if struct pointers and members are NULL or exist before using them.

13. File Operations

In C, file operations are important. However, if files are not opened or closed correctly, issues can arise. For example:

FILE *fp = fopen("test.txt", "r");
// Operate on file...
fclose(fp);

In the above code, if the fopen() function fails, it will return a NULL pointer, and using the fclose() function will result in an error.

Solution: Ensure that files are opened and closed correctly when using file operation functions, and check their return values.

14. Macro Definitions

In C, macro definitions are preprocessor directives that can be used to define constants, functions, etc. However, if macros are not used correctly, it can lead to program errors. For example:

#define SQUARE(x) x * x
int a = 2;
int b = SQUARE(a + 1); // Error: Incorrect result

In this example, SQUARE(a+1) expands to a+1*a+1, resulting in an incorrect result.

Solution: Use parentheses to clarify the order of operations in macro definitions and avoid using expressions with side effects in macros.

15. Multithreading

In C, multithreading programming is a complex technique. If thread synchronization mechanisms are not used correctly, errors such as data races and deadlocks can occur. For example:

void *print_message(void *ptr) {
    char *message = (char *) ptr;
    printf("%s\n", message);
    pthread_exit(NULL);
}
pthread_t t1, t2;
char *msg1 = "Thread 1";
char *msg2 = "Thread 2";
pthread_create(&t1, NULL, print_message, (void *) msg1);
pthread_create(&t2, NULL, print_message, (void *) msg2);

In this example, both threads will access the printf() function simultaneously, which may lead to jumbled output.

Solution: Use synchronization mechanisms to ensure correct cooperation between threads.

Interview Question

Here is an interview question about C language traps, please try to answer:

int a = 0, b = 1, c = 2, d = 3;
if (a++ && b-- || c++ && d--) {
    printf("case - %d %d %d %d\n", a, b, c, d);
} else {
    printf("case + %d %d %d %d\n", a, b, c, d);
}

What will the above code output? Why?

From: Embedded Lecture Hall

The source of this article is from the internet, and the copyright belongs to the original author. If there is any infringement, please contact for deletion.

15 Common C Language Traps in Embedded Development

Follow 【Learn Embedded Together】 to become better together..

If you find the article good, click “Share”, “Like”, “Recommend”!

Leave a Comment