# Common mistakes

Below is a list of common errors that programmers often make in C, along with sample code and detailed explanations of why they are mistakes:

1. **Missing semicolon at the end of a statement:**
    
    ```c
    int main() {
        printf("Hello, world!")
        return 0;
    }
    ```
    
    Explanation: In C, statements must end with a semicolon (`;`). Forgetting the semicolon at the end of a statement will result in a compilation error.
    
2. **Using undeclared variables:**
    
    ```c
    int main() {
        int x = y + 5;
        return 0;
    }
    ```
    
    Explanation: Variables must be declared before they are used. In this example, `y` is used without being declared, leading to a compilation error.
    
3. **Misplaced headers:**
    
    ```c
    int main() {
        #include <stdio.h>
        printf("Hello, world!");
        return 0;
    }
    ```
    
    Explanation: Header files (e.g., `<stdio.h>`) should be included at the beginning of the program, not within a function. Placing them inside a function may cause compilation issues.
    
4. **Missing 'return' statement in a non-void function:**
    
    ```c
    int add(int a, int b) {
        int sum = a + b;
    }
    ```
    
    Explanation: In a non-void function, a `return` statement is required to return a value. The absence of a `return` statement (or a missing value to return) will result in a compilation error.
    
5. **Using assignment operator instead of equality operator:**
    
    ```c
    int main() {
        int x = 5;
        if (x = 10) {
            printf("x is 10");
        }
        return 0;
    }
    ```
    
    Explanation: The single equals sign (`=`) is an assignment operator. To check for equality, use the double equals sign (`==`). The code above will assign 10 to `x` and always execute the `printf` statement.
    
6. **Array index out of bounds:**
    
    ```c
    int main() {
        int arr[5];
        arr[5] = 10;
        return 0;
    }
    ```
    
    Explanation: Array indices in C start from 0. Accessing or modifying an element outside the bounds of the array (in this case, index 5 in an array of size 5) leads to undefined behavior.
    
7. **Not checking for NULL after dynamic memory allocation:**
    
    ```c
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 5;
    ```
    
    Explanation: It's essential to check if the memory allocation (`malloc`) was successful. If `malloc` returns `NULL`, it indicates that the memory allocation failed, and using the pointer without checking can result in runtime errors.
    
8. **Using uninitialized variables:**
    
    ```c
    int main() {
        int x;
        printf("%d", x);
        return 0;
    }
    ```
    
    Explanation: Accessing the value of an uninitialized variable leads to undefined behavior. Always initialize variables before using them.
    
9. **Dividing by zero:**
    
    ```c
    int main() {
        int a = 10;
        int b = 0;
        int result = a / b;
        return 0;
    }
    ```
    
    Explanation: Division by zero is undefined in C and will result in a runtime error. Ensure that the denominator is not zero before performing division.
    
10. **Using '==\` to compare strings:**
    
    ```c
    char str1[] = "Hello";
    char str2[] = "Hello";
    if (str1 == str2) {
        printf("Strings are equal");
    }
    ```
    
    Explanation: Strings in C are arrays of characters, and you should use the `strcmp` function to compare strings. Using `==` compares the addresses of the arrays, not the content.
    
11. **Missing break statement in switch-case:**
    
    ```c
    int main() {
        int x = 2;
        switch (x) {
            case 1:
                printf("One");
            case 2:
                printf("Two");
        }
        return 0;
    }
    ```
    
    Explanation: Each `case` block in a `switch` statement should end with a `break` statement. If it's omitted, control will fall through to the next `case`, leading to unintended behavior.
    
12. **Using 'gets' function to read input:**
    
    ```c
    char name[50];
    gets(name);
    ```
    
    Explanation: The `gets` function is unsafe and can lead to buffer overflow vulnerabilities. Use `fgets` instead, which allows you to specify the maximum number of characters to read.
    
13. **Using the %f format specifier with 'double' in printf:**
    
    ```c
    double num = 3.14;
    printf("%f", num);
    ```
    
    Explanation: When printing a `double`, use the `%lf` format specifier in `printf`, not `%f`.
    
14. **Mixing 'float' and 'double' in comparisons:**
    
    ```c
    float f = 3.14;
    double d = 3.14;
    if (f == d) {
        printf("Equal");
    }
    ```
    
    Explanation: Comparing a `float` and a `double` directly can lead to unexpected results due to differences in precision. It's safer to compare values of the same type.
    
15. **Using 'sizeof' on a pointer:**
    
    ```c
    int *ptr;
    printf("%d", sizeof(ptr));
    ```
    
    Explanation: `sizeof` on a pointer returns the size of the pointer, not the size of the data it points to. If you want the size of the pointed data, use `sizeof(*ptr)`.
    
16. **Incorrect format specifier in printf for 'unsigned' types:**
    
    ```c
    unsigned int num = 42;
    printf("%d", num);
    ```
    
    Explanation: When printing an `unsigned` integer, use the `%u` format specifier, not `%d`.
    
17. **Using '==\` to compare floating-point numbers:**
    
    ```c
    float a = 0.1;
    float b = 0.2;
    if (a + b == 0.3) {
        printf("Equal");
    }
    ```
    
    Explanation: Floating-point numbers may have small rounding errors, and directly comparing them with `==` may lead to unexpected results. Use a tolerance or epsilon value for comparisons.
    
18. **Using 'goto' indiscriminately:**
    
    ```c
    int main() {
        int x = 0;
        goto label;
        x = 1;
    label:
        printf("%d", x);
        return 0;
    }
    ```
    
    Explanation: The indiscriminate use of `goto` can make code difficult to understand and maintain. In most cases, structured programming constructs like loops and functions are preferred.
    
19. **Assuming 'sizeof' for data types:**
    
    ```c
    int size = sizeof(int);
    ``
    ```
    

\`

Explanation: The size of data types may vary across different systems and compilers. Instead of hardcoding sizes, use `sizeof` to obtain the size dynamically.

1. **Ignoring the return value of 'scanf':**
    
    ```c
    int num;
    scanf("%d", &num);
    ```
    
    Explanation: The `scanf` function returns the number of successfully scanned items. Ignoring this return value may lead to unintended behavior, especially when reading user input.
    

1. **Incorrect use of the logical AND (**`&&`) and logical OR (`||`) operators:
    
    ```c
    int x = 5;
    if (x > 0 && x < 10 || x == 20) {
        printf("Condition met");
    }
    ```
    
    Explanation: The logical AND (`&&`) has higher precedence than the logical OR (`||`). To ensure correct evaluation, use parentheses to explicitly specify the grouping of conditions.
    
2. **Using 'printf' with the wrong format specifier:**
    
    ```c
    char ch = 'A';
    printf("%d", ch);
    ```
    
    Explanation: When printing a character with `printf`, use the `%c` format specifier, not `%d`.
    
3. **Incorrectly initializing a string:**
    
    ```c
    char str[5] = "Hello";
    ```
    
    Explanation: Strings in C require space for the null terminator (`'\0'`). In this case, the array size should be at least 6 to accommodate the characters in "Hello" plus the null terminator.
    
4. **Using 'sizeof' on an array parameter:**
    
    ```c
    void printArray(int arr[]) {
        printf("%d", sizeof(arr));
    }
    ```
    
    Explanation: In function parameters, an array decays into a pointer. Using `sizeof` on such a parameter gives the size of a pointer, not the size of the array. Pass the array size explicitly or use a different data structure like `std::vector` in C++.
    
5. **Missing 'return' statement in a non-void function:**
    
    ```c
    int divide(int a, int b) {
        if (b == 0) {
            printf("Error: Division by zero");
        }
    }
    ```
    
    Explanation: All code paths in a non-void function must have a `return` statement. The absence of a `return` statement, especially in conditional blocks, can lead to undefined behavior.
    
6. **Misusing the comma operator:**
    
    ```c
    int x = 5, y = 10, z;
    z = x, y;
    ```
    
    Explanation: The comma operator evaluates expressions from left to right and returns the result of the rightmost expression. In this case, `z` will be assigned the value of `x`, not `y`.
    
7. **Incorrect use of the 'typedef' keyword:**
    
    ```c
    typedef int* IntPtr;
    int x, y;
    IntPtr ptr = &x, y;
    ```
    
    Explanation: The `typedef` declaration applies only to the variable `ptr`, not `y`. To declare multiple variables of the same type, use separate declarations or a structure.
    
8. **Inconsistent use of 'const':**
    
    ```c
    const int a = 10;
    int* const ptr = &a;
    ```
    
    Explanation: Inconsistency in the use of `const`. Here, `ptr` is declared as a constant pointer, but it is assigned the address of a non-constant variable. Ensure consistency in the use of `const`.
    
9. **Using 'rand()' without seeding:**
    
    ```c
    int randomNum = rand();
    ```
    
    Explanation: The `rand()` function generates pseudo-random numbers, but it requires seeding using `srand()` to produce different sequences. Without seeding, the same sequence of numbers will be generated on each program run.
    
10. **Assuming 'sizeof' for structure padding:**
    
    ```c
    struct Example {
        char a;
        int b;
    };
    printf("%d", sizeof(struct Example));
    ```
    
    Explanation: The size of a structure may include padding for alignment. Instead of assuming the exact size, use `sizeof` to obtain the size dynamically.
    

1. **Using 'switch' with non-integral or non-enum types:**
    
    ```c
    double grade = 85.5;
    switch (grade) {
        case 90.0:
            printf("A");
            break;
        // other cases...
    }
    ```
    
    Explanation: The `switch` statement in C can only be used with integral types or enumerated types. Using it with non-integral types, like `double`, will result in a compilation error.
    
2. **Ignoring the return value of 'fclose':**
    
    ```c
    FILE *file = fopen("example.txt", "r");
    // operations on file...
    fclose(file);
    ```
    
    Explanation: The `fclose` function returns an integer value that indicates the success or failure of the operation. Ignoring this return value may lead to issues in handling file closures.
    
3. **Using 'printf' without format specifiers:**
    
    ```c
    int x = 42;
    printf(x);
    ```
    
    Explanation: The `printf` function expects format specifiers to match the types of the provided arguments. In this case, `%d` should be used as a format specifier for the integer variable `x`.
    
4. **Using a reserved keyword as an identifier:**
    
    ```c
    int double = 10;
    ```
    
    Explanation: Identifiers in C cannot be reserved keywords. In this example, using "double" as a variable name is invalid because "double" is a keyword in C.
    
5. **Missing 'break' statement in the 'default' case:**
    
    ```c
    int option = 2;
    switch (option) {
        case 1:
            printf("Option 1");
            break;
        case 2:
            printf("Option 2");
            // missing break statement
        default:
            printf("Default option");
    }
    ```
    
    Explanation: The `break` statement is missing in the `case 2` block. Without it, control will fall through to the `default` case, leading to unintended behavior.
    
6. **Using 'strcpy' without checking buffer size:**
    
    ```c
    char destination[10];
    char source[] = "Hello, World!";
    strcpy(destination, source);
    ```
    
    Explanation: The `strcpy` function does not check the size of the destination buffer. If the source string is longer than the destination buffer, it may lead to buffer overflow and undefined behavior. Use `strncpy` with explicit buffer size instead.
    
7. **Incorrect use of the conditional (ternary) operator:**
    
    ```c
    int x = 5, y = 10;
    int result = x > y ? x : y > 0 ? y : 0;
    ```
    
    Explanation: The conditional operator (`? :`) has right-to-left associativity. To avoid ambiguity, use parentheses to explicitly specify the grouping of conditions and expressions.
    
8. **Assuming ASCII values for character manipulation:**
    
    ```c
    char ch = 'A';
    ch += 1;
    ```
    
    Explanation: While ASCII values are commonly used, assuming a specific character encoding can lead to portability issues. Use character functions or constants from the `<ctype.h>` header for safer character manipulation.
    
9. **Using 'sizeof' with variable-length arrays (VLAs):**
    
    ```c
    int size = 5;
    int arr[size];
    printf("%d", sizeof(arr));
    ```
    
    Explanation: The `sizeof` operator may not behave as expected with variable-length arrays (VLAs). Instead of relying on `sizeof` for VLAs, consider using a constant or dynamic memory allocation.
    
10. **Incorrectly using the '&&' operator in place of '||':**
    
    ```c
    int x = 5;
    if (x > 0 && x < 2) {
        printf("Condition met");
    }
    ```
    
    Explanation: Using `&&` instead of `||` in a conditional statement may lead to unexpected behavior. Ensure that the logical operators are used correctly based on the intended logic.
