Skip to main content

C Best Practices

Writing good C code is not just about making it work—it's about making it maintainable, readable, and efficient. This guide covers the essential best practices and style guidelines that every C programmer should follow.

Naming Conventions​

c
// Variables: lowercase with underscores
int item_count = 0;

// Constants and macros: uppercase with underscores
#define MAX_BUFFER_SIZE 1024

// Functions: camelCase or lowercase with underscores
int calculateTotal(int price, int quantity);
int calculate_total(int price, int quantity);

// Struct names: PascalCase
typedef struct UserData {
char* name;
int age;
} UserData;

Code Formatting​

Indentation​

Use consistent indentation (4 spaces or 1 tab) for better readability:

c
if (condition) {
statement1;
statement2;
if (another_condition) {
nested_statement;
}
}

Braces​

Always use braces for control structures, even for single statements:

c
if (condition) {
single_statement;
}

Line Length​

Keep lines to a reasonable length (80-100 characters) for better readability:

c
int result = some_function(parameter1, parameter2,
parameter3, parameter4);

Comments​

Use Meaningful Comments​

c
// Calculate employee's total compensation
float total = base_salary + calculateBonus(performance_score);

Document Functions with Header Comments​

c
/**
* Calculates the area of a circle
*
* @param radius The radius of the circle
* @return The area of the circle
*/
double calculateCircleArea(double radius) {
return 3.14159 * radius * radius;
}

Avoid Obvious Comments​

c
// Handle edge case where input is negative
if (value < 0) {
return -1;
}

Memory Management​

Always Free Allocated Memory​

c
char* buffer = (char*)malloc(100);
if (buffer == NULL) {
// Handle allocation failure
return -1;
}

// Use buffer...

free(buffer); // Always free when done
buffer = NULL; // Avoid dangling pointer

Check Return Values​

c
FILE* file = fopen("data.txt", "r");
if (file == NULL) {
fprintf(stderr, "Error: Could not open file data.txt\n");
return -1;
}

// Use file...

fclose(file);

Function Design​

Keep Functions Small and Focused​

Each function should do one thing and do it well.

c
// Instead of one large function that does everything
void processData() {
// 1. Read data from file
Data* data = readDataFromFile("input.txt");

// 2. Validate data
if (validateData(data)) {
// 3. Transform data
transformData(data);

// 4. Save results
saveResults(data, "output.txt");
}

freeData(data);
}

Use Clear Parameter Names​

c
int calculateArea(int length, int width) {
return length * width;
}

Error Handling​

Check Return Codes​

c
int result = importantFunction();
if (result != SUCCESS) {
// Handle error
switch (result) {
case ERROR_FILE_NOT_FOUND:
// Handle specific error
break;
// Other cases...
default:
// Handle unknown error
break;
}
}

Use Assert for Development​

c
#include <assert.h>

void processArray(int* array, int size) {
assert(array != NULL && "Array cannot be NULL");
assert(size > 0 && "Size must be positive");

// Process array...
}

Security Considerations​

Validate Input​

c
void processUserInput(char* input) {
// Check for NULL
if (input == NULL) {
return;
}

// Check length to avoid buffer overflows
if (strlen(input) > MAX_INPUT_LENGTH) {
fprintf(stderr, "Input too long\n");
return;
}

// Now it's safe to process
// ...
}

Use Safe Functions​

c
char buffer[100];
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0'; // Ensure null termination

Performance Optimization​

Premature Optimization​

Write clear code first, then optimize where needed:

c
// First write clear, correct code
for (int i = 0; i < array_size; i++) {
array[i] = processItem(array[i]);
}

// Only optimize after profiling shows this is a bottleneck

Loop Optimization​

c
// Pre-calculate loop bounds
int size = getArraySize();
for (int i = 0; i < size; i++) {
// Process...
}

Tools for Maintaining Quality​

  • Static Analysis: Use tools like cppcheck, clang-tidy, or splint
  • Memory Checking: Use valgrind to detect memory leaks
  • Formatting: Use clang-format to maintain consistent styling
  • Documentation: Use tools like Doxygen for generating documentation

Conclusion​

Following these best practices will help you write C code that is not only correct but also maintainable, secure, and efficient. Remember that consistency is key—choose a style guide (like the Linux kernel style guide or GNU style) and stick with it throughout your project.

Further Reading​



If you spot any mistakes on this website, please let me know at feedback@compilenrun.com. I’d greatly appreciate your feedback! :)