Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 6: Comparison of Python and C

Moving from Python to C means learning where the two languages differ and where they are alike. This chapter covers the major differences in syntax, data types, and memory management, along with the common pitfalls, so that you can work with C effectively as a Python programmer.

6.1 Syntax differences

Python and C share many programming concepts, but their syntax is quite different.

6.1.1 Indentation vs. braces

Python:

if x > 0:
    print("Positive")
else:
    print("Non-positive")

C:

#include <stdio.h>

int main() {
    int x = 10;

    if (x > 0) {
        printf("Positive\n");
    } else {
        printf("Non-positive\n");
    }

    return 0;
}

Explanation:

  • Python marks blocks of code with indentation. C uses braces {}.
6.1.2 Variable declarations

Python:

x = 10
y = 20.5
name = "Alice"

C:

#include <stdio.h>

int main() {
    int x = 10;
    float y = 20.5;
    char name[] = "Alice";

    return 0;
}

Explanation:

  • Python uses dynamic typing, so variable types are inferred.
  • C requires you to declare each variable explicitly, with its type.

6.2 Data type differences

Python has a variety of high-level data types. C’s types are more primitive, and C requires explicit memory management.

6.2.1 Lists vs. arrays

Python:

numbers = [1, 2, 3, 4, 5]
print(numbers[2])  # Output: 3

C:

#include <stdio.h>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    printf("%d\n", numbers[2]);  // Output: 3

    return 0;
}

Explanation:

  • Python lists can grow dynamically and hold elements of different types.
  • C arrays have a fixed size and hold elements of the same type.
6.2.2 Strings

Python:

greeting = "Hello, World!"
print(greeting)

C:

#include <stdio.h>

int main() {
    char greeting[] = "Hello, World!";
    printf("%s\n", greeting);

    return 0;
}

Explanation:

  • Python strings are high-level objects.
  • C strings are arrays of characters terminated by a null character (\0).

6.3 Memory management

Python manages memory for you. In C you manage it manually, with functions such as malloc, calloc, realloc, and free.

6.3.1 Dynamic memory allocation

Python:

numbers = [1, 2, 3, 4, 5]
numbers.append(6)
print(numbers)  # Output: [1, 2, 3, 4, 5, 6]

C:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *numbers = (int *)malloc(5 * sizeof(int));
    if (numbers == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    for (int i = 0; i < 5; i++) {
        numbers[i] = i + 1;
    }

    // Resize the array
    int *resized = (int *)realloc(numbers, 6 * sizeof(int));
    if (resized == NULL) {
        printf("Memory reallocation failed\n");
        free(numbers);
        return 1;
    }
    numbers = resized;
    numbers[5] = 6;

    for (int i = 0; i < 6; i++) {
        printf("%d ", numbers[i]);
    }

    free(numbers);  // Free the allocated memory
    return 0;
}

Explanation:

  • Python manages the list’s memory automatically.
  • In C, you allocate and deallocate the memory yourself.
  • If realloc can’t resize the block, it returns NULL and leaves the original block allocated. That’s why the result goes into a separate pointer, resized. Writing numbers = realloc(numbers, ...) would overwrite your only pointer to the old block with NULL on failure, and the block could never be freed.

6.4 Common pitfalls

Watch out for these common mistakes when you move from Python to C.

6.4.1 Buffer overflows

C gives you low-level access to memory, and if you aren’t careful, that can lead to buffer overflows.

Example of a buffer overflow:

#include <stdio.h>
#include <string.h>

int main() {
    char buffer[10];
    strcpy(buffer, "This is a very long string");  // Unsafe, causes buffer overflow

    printf("Buffer: %s\n", buffer);
    return 0;
}

Solution: Use a safer function such as strncpy:

#include <stdio.h>
#include <string.h>

int main() {
    char buffer[10];
    strncpy(buffer, "This is a very long string", sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';  // Ensure null-termination

    printf("Buffer: %s\n", buffer);
    return 0;
}
6.4.2 Dangling pointers

A dangling pointer points to a memory location that has been freed.

Example of a dangling pointer:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(sizeof(int));
    *ptr = 10;

    free(ptr);
    // ptr is now a dangling pointer
    // printf("Value after free: %d\n", *ptr); // This would lead to undefined behavior

    return 0;
}

Solution: Set the pointer to NULL after you free it:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(sizeof(int));
    *ptr = 10;

    free(ptr);
    ptr = NULL;  // Avoids dangling pointer

    return 0;
}
6.4.3 Memory leaks

A memory leak occurs when allocated memory is not freed.

Example of a memory leak:

#include <stdlib.h>

void createLeak() {
    int *ptr = (int *)malloc(10 * sizeof(int));
    // Memory allocated is not freed
}

int main() {
    createLeak();
    return 0;
}

Solution: Make sure every block of memory you allocate is freed:

#include <stdlib.h>

void createLeak() {
    int *ptr = (int *)malloc(10 * sizeof(int));
    // Use the memory
    free(ptr);  // Free the allocated memory
}

int main() {
    createLeak();
    return 0;
}

6.5 Best practices in both languages

6.5.1 Code readability

In both languages, use meaningful variable names and write comments. Keep your indentation consistent in Python and your use of braces {} consistent in C.

6.5.2 Error handling

Python handles errors with exceptions. In C, you use return values and error codes.

Python:

try:
    file = open('example.txt', 'r')
    content = file.read()
    print(content)
except IOError:
    print("Error opening file")

C:

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        printf("Error opening file\n");
        return 1;
    }

    char buffer[256];
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }

    fclose(file);
    return 0;
}
6.5.3 Memory management

Python has automatic garbage collection. In C, you manage memory by hand with malloc/free.

Python:

data = [1, 2, 3, 4, 5]
# No need to free memory explicitly

C:

#include <stdlib.h>

int main() {
    int *data = (int *)malloc(5 * sizeof(int));
    if (data == NULL) {
        return 1;
    }

    // Use the memory

    free(data);  // Free the allocated memory
    return 0;
}