Skip to content

Instantly share code, notes, and snippets.

@davidzchen
Last active June 16, 2024 09:01
Show Gist options
  • Save davidzchen/9187984 to your computer and use it in GitHub Desktop.
Save davidzchen/9187984 to your computer and use it in GitHub Desktop.
Sample C code using the Linux kernel coding style
/*
* Sample file using the Linux kernel coding convention.
*
* https://www.kernel.org/doc/Documentation/CodingStyle
*
* General rules:
* - Indents are tabs and must be 8 spaces wide.
* - Each line must be at most 80 characters long.
* - Use C-style comments.
* - File names should be lower-case.c
*/
#include <stdlib.h>
#include <stdbool.h>
/* For macros, use ALL_CAPS separated by underscore: */
#define FLAG_FOO 0x0
/*
* If a macro's replacement is not just a literal, enclose it in parentheses:
*/
#define FLAG_BAZ (0x1 << 3)
/*
* It appears that the Linux kernel codebase tends to use #defines for
* constants. Global constants are treated similar to global variables.
*/
const int state_foo = 0;
/* Enum values can either look like macros: */
enum mode {
MODE_FOO,
MODE_BAR,
MODE_BAZ,
MODE_QUX
};
/*
* Names of members of structs are lower_case and separated by underscores.
* Avoid typedef-ing types unless the type is intended to be used as an opaque
* type.
*/
struct sample {
int first_field;
int second_field;
Mode mode;
State state;
struct sample *next;
};
/*
* Function names are lower_case. Opening braces on the next line.
* Use gotos so that there is only one exit point for a given function.
*/
int sample_equal(struct sample *self, struct sample *other)
{
int ret = 0;
/* Local variables are lower_case and separated by underscores. */
if (self == NULL && other == NULL) {
ret = 1;
goto out;
}
if (self == NULL || other == NULL) {
goto out
}
/*
* For statements that span multiple lines, use spaces for alignment
* only.
*/
if (self->first_field == other->first_field &&
self->second_field == other->second_field &&
self->state == other->state &&
self->mode == other->mode &&
self->next == other->next) {
ret = true;
}
out:
return ret;
}
/*
* For function declarations that span multiple lines, indent them
* "substantially to the right."
*/
struct sample *sample_new(int first_field, int second_field, int mode,
int state, struct sample *next)
{
struct sample *sample = (struct sample *) malloc(sizeof(*sample));
if (sample == NULL) {
sample = NULL;
goto out;
}
memset(sample, 0, sizeof(sample));
sample->first_field = first_field;
sample->second_field = second_field;
sample->mode = mode;
sample->state = state;
sample->next = next;
out:
return sample;
}
struct sample *sample_clone(struct sample *sample)
{
if (sample == NULL) {
return NULL;
}
/*
* For function calls that span multiple lines, align them to the
* right.
*/
return sample_new(sample->first_field, sample->second_field,
sample->mode, sample->state, sample->next);
}
/*
* For function declarations (and function calls) where you cannot fit
* the parameters with the first after the opening parentheses, then align
* the parameters indented four spaces on the next line:
*/
static void sample_do_something_with_a_long_name(
struct sample *sample, int parameter_with_a_long_name,
int another_parameter, int another_parameter)
{
if (sample == NULL) {
goto out;
}
/*
* else and else if comes after the previous closing brace and not on
* the next line.
*/
int local_variable;
if (parameter_with_a_long_name == MODE_FOO) {
local_variable = 1;
} else {
local_variable = 0;
}
sample->first_parameter += another_parameter;
sample->second_parameter |= local_variable;
out:
return;
}
@jacekmigacz
Copy link

line 90:

struct sample _sample = (struct sample *) malloc(sizeof(_sample));

why casting (void *) in C?

@cfrank
Copy link

cfrank commented May 18, 2016

It's just example code, I'm sure not much thought went into it. But you can always cast void * to whatever you want. Pre ANCI C when malloc returned char * it was common practise to cast the return value of malloc. Even in later versions it's not harmful just redundant.

@shaoner
Copy link

shaoner commented Sep 9, 2016

const int state_foo = 0;

Not sure why, but the kernel checkpatch.pl script won't allow globals initialization of 0 (probably because the compiler does it already)

@a3f
Copy link

a3f commented Mar 28, 2017

const int state_foo = 0;

@shaoner Some older GCC versions erroneously reserved space in the binary for globals explicitly initialized to zero, so that might be a reason to it being disallowed (In addition to it being redundant).

Besides, the definition itself is also a bad idea. Unlike in C++, C consts at global scope are still extern. So you will have link errors if some other translation unit defines the same constant. The alternative static const still doesn't solve the issue that the variable won't be usable in a place where integer constant expressions are expected.

@hyt72
Copy link

hyt72 commented Dec 17, 2020

Do not unnecessarily use braces where a single statement will do.

if (condition)
        action();

@0xFF1E071F
Copy link

can you add sample switch - case statement
thank you

@hyt72
Copy link

hyt72 commented Dec 18, 2020

switch (suffix) {
case 'G':
case 'g':
        mem <<= 30;
        break;
case 'M':
case 'm':
        mem <<= 20;
        break;
case 'K':
case 'k':
        mem <<= 10;
        /* fall through */
default:
        break;
}

@0xFF1E071F
Copy link

switch (suffix) {
case 'G':
case 'g':
        mem <<= 30;
        break;
case 'M':
case 'm':
        mem <<= 20;
        break;
case 'K':
case 'k':
        mem <<= 10;
        /* fall through */
default:
        break;
}

Thank you very much =)

@trr
Copy link

trr commented Jul 22, 2021

For function-like macros, use function_naming() convention so they're like functions or UPPER_CASE() so they're like constant macros, or otherwise? The kernel doc is ambivalent, other than suggesting they be converted to inline functions

@Aruna-Hewapathirane
Copy link

Aruna-Hewapathirane commented Nov 14, 2021

line 90:

struct sample _sample = (struct sample *) malloc(sizeof(_sample));

why casting (void *) in C?

The name "malloc" stands for memory allocation.

The function malloc() returns a pointer of type void, and you can use the cast operator to convert it to any type.

Syntax of malloc()
pointer_variable = (castType*) malloc(size);

Example
pointer_variable = (float*) malloc(10 * sizeof(float));

The above statement allocates 40 bytes of memory. It's because the size of float is 4 bytes. And, the pointer pointer_variable holds the address of the first byte in the allocated memory.

The expression results in a NULL pointer if the memory cannot be allocated

To make the program portable, many programmers use the sizeof operator along with the malloc as in the following statement, where a portion of memory is required to hold ten intergers.

pointer_variable = (int *) malloc(10 * sizeof(int));

If a specific machine is using a different interger size, this code will still work properly.

It is 5 years since the question was asked, hopefully the answer will help clarify matters :-)

@yamirui
Copy link

yamirui commented Apr 17, 2022

goto should be used so there's only one exit point

What a load of nonsense, unless cleanup needs to be done, you return directly, because it makes the intent clear instead of having to go down to the bottom of the function and read the code below a WORTHLESS label that immediately hits a return statement. This is specifically adressed in the real Linux kernel coding style guide.

@FoxieFlakey
Copy link

can you add cases what should do for short function types like void (*read)(int fd, void* udata) and longer one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment