foobaz - C style

C11: The function called at program startup is named main.

C11: The implementation declares no prototype for this function.

C11: The main function shall be defined with a return type of int

Style; functions; have the opening brace at the beginning of the next line.

C11: The main function defined with no parameters:

int main(void)
{
	/* ... */
}

C11: The main function defined with two parameters...

Style; main function; with two parameters:

int main(int argc, char* argv[])
{
	/* ... */
}

Style C23; function pointer param; use array notation; to be explicit that the pointer can not be nullptr.

Style C23; main function; with two parameters:

int main(int argc, [[maybe_unused]] char* argv[argc+1])
{
	/* ... */
}

Style C23; null; Do not use the macro NULL; use nullptr instead.

Style; selection statements; always use brackets; to be explicit for the secondary block.

Style; selection statements; the first bracket for the secondary block begins on the same line:

if (true) {
	/* ... */
} else if (false) {
	/* ... */
} else {
	/* ... */
}

Style; iteration statements; always use brackets; to be explicit for the secondary block.

Style; iteration statements; the first bracket for the secondary block begins on the same line:

for (size_t ix = 0; ix < 5; ix += 1) {
	/* ... */
}

Style; declaring pointer; left-binding rule:

/*
 * When declaring pointer data or a function that returns a pointer type,
 * the preferred use of ''*'' is adjacent to the type.
*/
char* name;
unsigned long long memparse(char* ptr, char* retptr[]);
char* match_strdup(substring_t* s);
char const* const path_name[[deprecated]];

Style; declaring pointer; right-binding rule:

/*
 * When declaring pointer data or a function that returns a pointer type,
 * the preferred use of ''*'' is adjacent to the name.
*/
char *name;
unsigned long long memparse(char *ptr, char **retptr);
char *match_strdup(substring_t *s);
char const *const path_name[[deprecated]];

Style; declaring pointer; follow the pattern that the project uses; prefere the left-binding rule over the right-binding rule in most cases.

Style; function pointer param; char s[], char *s, and char* s are equivalent, use the latter.

Style; pointer; use a name like px or ptr for pointer variables: https://godbolt.org - example

#include <stdlib.h>

void swap(int* px, int* py)
{
	// int* px -- (px) is a pointer-to type (int)

	int tmp = *px;
	// *px -- value-of (px)

	*px = *py;
	*py = tmp;
}

int main(void)
{
	int a = 2;
	int b = 3;

	swap(&a, &b);
	// &a -- address-of (a)

	return EXIT_SUCCESS;
}

Style; pointer and string example: https://godbolt.org - example

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

/* Do not use this style. */
char *bad_style(char *sp)
{
	int x = 5, *ip = &x;
	printf("x = %d\n", x);
	printf("ip = %ld\n", ip);
	printf("x = %d\n", *ip);
	printf("%s\n", sp);
	return sp;
}

/* Use this style. */
char* better_style(char* str)
{
	int x = 5;
	int* px = &x;
	printf("x = %d\n", x);
	printf("ip = %ld\n", px);
	printf("x = %d\n", *px);
	printf("%s\n", str);
	return str;
}

int main(void)
{
	char str[] = "foobaz C style";
	char* ptr = better_style(bad_style(str));
	if (str == ptr) {
		printf("same memory address");
	}
	return EXIT_SUCCESS;
}

Style; if statement; do not compare to 0, false, or true:

if (return_code != 0) {
	/* Use the logic instead that an if statement checks if it is non zero. */
} else if (success == true) {
	/* Use the boolean value directly like ''if (success) {}'' */
}

The Boolean data type in C is also considered an unsigned type.

The values false and true, corresponding to 0 and 1, so there are no negative values.

You will probably rarely need bool variables.

Style C23; variables; always use the zero initialization syntax:

int a = {}; /* Do not use this style */
int b = { 0 };
int c = { 2 };
int many_zeros[100] = {}; /* Available in C11; do not use this style. */
int many_zeros[100] = { 0 }; /* Available in C11 */
int many[100] = { [50] = 3, [90] = 7 }; /* Available in C11 */
int more[10] = {
	[3] = 3,
	[4] = 7, /* When each initializer is on its own line then use trailing comma. */
};

Inspiration:

Then use the Linux kernel coding style

Example A - C11

https://godbolt.org - example

#include <stdio.h>
#include <stdlib.h>
/* The <stdlib.h> header shall define NULL as described in <stddef.h>. */
#include <stdbool.h>
/* Before C23; the names bool as well as the constants false and true only came through the inclusion of <stdbool.h>. */
#include <stddef.h>

int main(int argc, char* argv[])
{
	if (argc != 2) {
		fprintf(stderr, "Usage: %s <file>\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	FILE* file = fopen(argv[1], "r");
	if (file == NULL) {
		perror(argv[1]);
		return EXIT_FAILURE;
	}
	/* Other code omitted */
	if (fclose(file)) {
		return EXIT_FAILURE;
	}
	#define pattern_size 4
	bool pattern[pattern_size] = { [1] = true, [2] = true };
	for (size_t ix = 0; ix < pattern_size; ix += 1) {
		if (pattern[ix]) {
			printf("1\n");
		} else {
			printf("0\n");
		}
	}
	return EXIT_SUCCESS;
}

Example B - C23

https://godbolt.org - example

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

int main(int argc, [[maybe_unused]] char* argv[argc+1])
{
	if (argc != 2) {
		fprintf(stderr, "Usage: %s <file>\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	FILE* file = fopen(argv[1], "r");
	if (file == nullptr) {
		perror(argv[1]);
		return EXIT_FAILURE;
	}
	/* Other code omitted */
	if (fclose(file)) {
		return EXIT_FAILURE;
	}
	constexpr size_t pattern_size = { 4 };
	bool pattern[pattern_size] = { [1] = true, [2] = true };
	for (size_t ix = { 0 }; ix < pattern_size; ix += 1) {
		if (pattern[ix]) {
			printf("1\n");
		} else {
			printf("0\n");
		}
	}
	return EXIT_SUCCESS;
}