Code Style in C
Table of contents
Eagleson’s Law : “Any code of your own that you haven’t looked at for six or more months might as well have been written by someone else.”
Writing good code is not just about telling the computer what to do, it is communicating to other people what you have told the computer to do!
Use this guide to help you write consistent and readable code.
Introduction
Code style is a hugely important aspect of coding which is often neglected by novices. Indeed, a cursory glance at how code is written will often tell you if it has been written by a professional or a novice.
Professional programmers stick to very strict code style guidelines and indeed, are often forced to by their employers. Ensuring that all employees use the same coding style means that they can all easily read each other’s code.
Given the age of the C programming language there are many different style guides. For example NASA have their own guidelines to keep code understandable and testable detailed in this journal article aka the Power of Ten which are summarised in this video
We will follow the typical conventions, based on the C Bible sometimes shortened to K&R after the authors, and then expanded into things like Google’s C++ Guide.
Following this clear, consistent C style will make you into a better and more professional programmer.
End of lines and files
Do not put trailing whitespace at the end of lines. The final character in a source file should be a newline after the closing } (no extra blank lines at the end).
Good
#include <stdio.h>
int main(void) {
printf("Hello, C!\n");
return 0;
}
Bad (trailing spaces shown as ·, stray blank lines at end)
#include <stdio.h>··
int main(void) {··
printf("Hello, C!\n");··
return 0;··
}··
Tabs and indentation
Use spaces, not tabs. Use 2 spaces per indent level. This is the source of many an argument online!
Good
int clamp(int x, int lo, int hi) {
if (x < lo) {
return lo;
} else if (x > hi) {
return hi;
}
return x;
}
Bad (tabs and inconsistent width)
int clamp(int x, int lo, int hi) {
\tif (x < lo) {
\t\treturn lo;
\t} else if (x > hi) {
\t\treturn hi;
\t}
\treturn x;
}
Horizontal whitespace
Use spaces to make expressions readable and consistent.
Around operators
Good
int sum = a + b * 4 + 5;
Bad
int sum=a+b*4+5;
In expressions and after commas
Good
int c = sum * 4 + 5;
int rgb[3] = { 255, 127, 0 };
Bad
int c=sum*4+5;
int rgb[3]={255,127,0};
Braces and parentheses
- Put one space before an opening brace
{(K&R). - No spaces just inside parentheses.
- No space before semicolons.
- For arrays, no space before
[.
Good
for (int i = 0; i < 10; i++) {
/* ...Code... */
}
int main(void) {
int array[5] = { 1, 2, 3, 4, 5 };
return 0;
}
Bad
for(int i=0;i<10;i++){
/* ...Code... */
}
int main ( void ){
int array [ 5 ] = {1,2,3,4,5};
return 0 ;
}
Conditionals and else
- Space after keywords (
if,while,for). - Space around
else:} else {.
Good
if (n < 0) {
printf("Negative\n");
} else {
printf("Non-negative\n");
}
Bad
if(n<0){
printf("Negative\n");
}else{
printf("Non-negative\n");
}
for loop semicolons
Put a space after each semicolon inside for headers.
Good
for (int i = 0; i < 10; i++) {
/* ... */
}
Bad
for (int i=0;i<10;i++){
/* ... */
}
Inline comments
- Space after
//. - Leave two spaces before the start of an inline comment following code.
Good
int top_score = 0; // highest score seen so far
Bad
int top_score=0;//highest score seen so far
Vertical whitespace
Minimise blank lines. Use one blank line between functions. Don’t start or end a function with a blank line. Inside a function, use blank lines sparingly to separate logical sections.
Too much vertical whitespace
int calc_sum(int a, int b) {
int sum = a + b;
return sum;
}
int calc_product(int a, int b) {
int product = a * b;
return product;
}
Better
int calc_sum(int a, int b) {
int sum = a + b;
return sum;
}
int calc_product(int a, int b) {
int product = a * b;
return product;
}
Examples
Examples of properly structured loops and conditionals.
for loop
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
while loop
#include <stdio.h>
void print_to_9(void) {
int i = 0;
while (i < 10) {
printf("%d\n", i);
i++;
}
}
if / else if chain
#include <stdio.h>
void print_classification(int grade) {
if (grade > 70) {
printf("Class I\n");
} else if (grade > 60) {
printf("Class II.i\n");
} else if (grade > 50) {
printf("Class II.ii\n");
} else if (grade > 40) {
printf("Class III\n");
} else {
printf("Fail\n");
}
}
A long if / else if chain can include judicious blank lines to group related cases:
if (grade > 70) {
printf("Class I\n");
} else if (grade > 60) {
printf("Class II.i\n");
} else if (grade > 50) {
printf("Class II.ii\n");
} else if (grade > 40) {
printf("Class III\n");
} else {
printf("Fail\n");
}
Naming
Consistency is key. Prefer descriptive, lowercase_with_underscores for variables, functions, and files.
Variables
Good
double price_of_item = 0.99;
int sensor_count = 3;
Bad
double p = 0.99;
int SensorCount = 3;
Functions
Use verbs and be descriptive.
Good
int calc_average_score(const int *scores, int n);
void led_set_brightness(int value);
Bad
int avg(int*, int);
void set(int v);
Structs and typedefs (C has no classes)
C does not have classes. Use structs for related data and consider a typedef for readability. Prefer no leading underscores (some leading-underscore names are reserved in C).
Good
typedef struct {
int x;
int y;
} point_t;
void point_move(point_t *p, int dx, int dy);
Bad
struct _Point { // avoid leading underscore
int X; // avoid capitalised field names
int Y;
};
Internal (module-private) identifiers
C has no namespaces. Use a module prefix and static for internal linkage.
// In file "net_buf.c" (module prefix: net_buf_)
static size_t net_buf_clamp(size_t n, size_t hi) { return n > hi ? hi : n; }
Macros
Use UPPER_CASE for macros and constants. Prefer static inline functions over function-like macros when possible.
#define MAX_SENSORS 8
static inline int square(int x) {
return x * x;
}
Filenames
Lowercase with underscores. Use .c for source and .h for headers.
my_source_file.c
my_header_file.h
Comments
Code Tells You How, Comments Tell You Why
Prefer C99 // comments over /* ... */ block comments for most cases. Use a space after //.
Good
// This computes the checksum over a buffer.
Bad
/*This computes the checksum over a buffer.*/
Provide a brief, useful file header comment at the top of each file.
// Program: sum_primes.c
// Purpose: Calculate the sum of the first n prime numbers
// Author: Your Name
// Date: 2025-09-24
Use descriptive names to avoid pointless comments.
Pointless
int z = 0; // Variable to store top score
Better
int top_score = 0;
Comment what’s non-obvious: complex logic, invariants, preconditions, and side effects. Place short comments above a block, and end-of-line comments where it truly clarifies.
Before (vague)
// check if all lives lost and if so, call game over function
if (lives_left == 0) {
game_over();
}
After (self-documenting + concise)
if (lives_left == 0) { // no retries remaining
game_over();
}
Functions
Break code into small, focused functions. This improves testing, reuse, and readability. There’s no hard line, but if a function grows beyond ~20–40 lines, consider splitting it. The NASA Power of Ten Guidelines suggest limiting the code within a function to a single printed A4 page.
No blank lines at the start or end of a function. Use descriptive names, a general rule of thumb is that the name should include a verb, to say what the code does.
One-line function
int product(int a, int b) { return a * b; }
Multi-line (no leading/trailing blank lines)
#include <stdbool.h>
bool in_range(int x, int lo, int hi) {
if (x < lo) return false;
if (x > hi) return false;
return true;
}
Single-exit with cleanup
Writing functions with a single return point makes cleanup and error handling easier because all resource releases and final actions happen in one predictable place. If you have multiple return statements then it is harder to understand when the functions stops, and what code it will return. A single return also improves maintainability and reduces the risk of leaks or inconsistent exit paths as the function grows in complexity.
#include <stdio.h>
#include <stdbool.h>
int sum_to_n(int n) {
bool ok = false;
int sum = 0;
if (n >= 0 && n <= 10000) { // basic guard (choose a sensible upper bound)
ok = true;
for (int i = 1; i <= n; i++) {
sum += i;
}
printf("sum(1..%d) = %d\n", n, sum);
} else {
printf("invalid n: %d\n", n);
}
return ok ? 0 : -1; // single exit
}
int main(void) {
sum_to_n(5); // prints: sum(1..5) = 15
sum_to_n(-3); // prints: invalid n: -3
return 0;
}
Summary
Take care when writing code and get into the habit of applying clear and consistent styling. It really is important and puts you on track to becoming a professional software engineer.
Writing poorly structured and inconsistently styled code is a distinctive signature of a novice programmer. It suggests the developer cuts corners and doesn’t take pride in their work.
If you worked for a company and were in charge of hiring a graduate software engineer, which one of these would you employ?