Skip to content

Guidelines for modern C coding, including style conventions and layout organization.

License

Notifications You must be signed in to change notification settings

coding-pelican/c-style-guide

Repository files navigation

C Style Guide

Guidelines for modern C coding, including style conventions and layout organization.

Still a work in progress.

Layout & Order of Groupings

Public ::= extern

Private ::= static

Header files

The following groupings should appear in all C header files in the following order:

1.  Heading comment
  2.  Doxygen file prologue
  3.  Release statement and copyright

4-s.  Header file include guard (opening)
5-s.  C language link (opening)

  6.  Header file inclusions (when NEEDED instead of forward declarations)
  7.  Pre-processor definitions
  8.  Forward declarations (when NEEDED in this header file)

  9.  Public types (definitions: const, enum, struct, ...)
  10. Public data (declarations: global, extern, static with extern)
  11. Inline functions (definitions)
  12. Public function prototypes (declarations)

5-e.  C language link (closing)
4-e.  Header file include guard (closing)

example.h:

/**
 * @file example.h
 * @author {YourName} ({your.email_address@where.com})
 *
// 2. Doxygen file prologue
 * @brief Example header file.
 * @details This header file shows an example of the layout and grouping order.
 *
// 3. Release statement and copyright
 * @version {major}.{minor}.{path}{-{pre.release}(optional)}
 * @date YYYY-MM-DD
 *
 * @copyright Copyright {YYYY}. {Your{Name|Company}} All rights reserved.
            | Released under the {YourLicense a}. See LICENSE file for details.
 */

// 4-s. Header file include guard (opening)
#ifndef EXAMPLE_H
#define EXAMPLE_H

// 5-s. C language link (opening)
#if defined(__cplusplus)
extern "C" {
#endif // defined(__cplusplus)

// 6. Header file inclusions (when NEEDED instead of forward declarations)
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "foo.h"

// 7. Pre-processor definitions
#define EXAMPLE_MAX_SIZE 100

// 8. Forward declarations (when NEEDED in this header file)
typedef struct Foo Foo;

// 9. Public types (definitions)
enum eExampleType {
    eExampleType_None = -1,
    eExampleType_Foo  =  0,
    eExampleType_Bar,
    eExampleType_Baz,
    kExampleType_Count
};
typedef int32_t ExampleType;

typedef struct Point Point;
struct Point {
    int x;
    int y;
};

typedef struct Bar Bar;
struct Bar {
    ExampleType type;
    Foo foo;
    Point p;
};

static char const* const kBarTypeName = "Bar";
static int         const kBarInitX = 0;
static int         const kBarInitY = 0;
static Point       const kBarInitPoint = {kBarInitX, kBarInitY};

// 10. Public data (declarations)
extern int gBarCreatedCount;
extern int gBarDestroyedCount;

// 11. Inline functions (definitions)
static inline Point Point_AddPoint(Point p, Point q) {
    return (Point){
        .x = p.x + q.x,
        .y = p.y + q.y
    };
}

static inline Point Point_Scale(Point p, int s) {
    return (Point){
        .x = p.x * s,
        .y = p.y * s
    };
}

// 12. Public function prototypes (declarations)
bool ProcessData(uint8_t const* refData, size_t size);
Bar* Bar_Create();
Bar* Bar_Initialize(Bar* outBar, Foo foo, Point p);
void Bar_Destroy(Bar** outBarPtr);

// 5-e. C language link (closing)
#if defined(__cplusplus)
}
#endif // defined(__cplusplus)

// 4-e. Header file include guard (closing)
#endif // !EXAMPLE_H

Source files

The following groupings should appear in all C source files in the following order:

1.  Heading comment
  2.  Doxygen file prologue
  3.  Release statement and copyright

4.  Header file inclusions (only those that are NECESSARY)
5.  Pre-processor definitions

6.  Private types (definitions)
7.  Private data (definitions)
8.  Private function prototypes (declarations)

9.  Public data (definitions)
10. Public functions (definitions)
11. Private functions (definitions)

example.c

// 1. Heading comment
/**
 * @file example.c
 * @author {YourName} ({your.email_address@where.com})
 *
// 2. Doxygen file prologue
 * @brief Example source file.
 * @details This source file provides implementations for functions declared in example.h.
 *
// 3. Release statement and copyright
 * @version {major}.{minor}.{path}{-{pre.release}(optional)}
 * @date YYYY-MM-DD
 *
 * @copyright Copyright {YYYY} {Your{Name|Company}}. All rights reserved.
            | Released under the {YourLicense a}. See LICENSE file for details.
 */

// 4. Header file inclusions (only those that are NECESSARY)
#include "example.h"
#include <stdbool.h> // Include standard boolean type
#include <stdio.h>   // Include standard I/O library for printf
#include <stdlib.h> // Include standard library for malloc

// 5. Pre-processor definitions
#define EXAMPLE_ADD(_x, _y) ((_x) + (_y))
#define EXAMPLE_SUB(_x, _y) ((_x) + (_y))
#define EXAMPLE_MAX(_a, _b) (((_a) < (_b)) ? (_b) : (_a))
#define EXAMPLE_MIN(_a, _b) (((_a) > (_b)) ? (_b) : (_a))

#define EXAMPLE_DEBUG
#ifdef EXAMPLE_DEBUG
#  define ASSERT(_condition)                               \
    do {                                                   \
        if (!(_condition)) {                               \
            (void)fprintf(                                 \
                stderr, "%s:%d: Assertion '%s' failed.\n", \
                __FILE__, __LINE__, #_condition            \
            );                                             \
            __builtin_trap();                              \
        }                                                  \
    } while(0)
#else
#  define ASSERT(condition) ((void)0)
#endif // EXAMPLE_DEBUG

#define EXAMPLE_SWAP(_T, _a, _b) \
    do {                         \
        _T __t = (_a);           \
        (_a)   = (_b);           \
        (_b)   = __t;            \
    } while (0)

#define EXAMPLE_DO_ASSIGN(_a, _b) do { (_a) = (_b); } while (0)

#define EXAMPLE_TYPE_IS_FOO(_obj) ((_obj).type == eExampleType_Foo)

// 6. Private types (definitions)
typedef struct Baz Baz;
struct Baz {
    ExampleType type;
    Bar         bar;
    float       value;
};

// 7. Private data (definitions)
static int sCurrentBarCount = 0;

// 8. Private function prototypes (declarations)
static void TestPoint();
static char const* ExampleType_ToStringType(ExampleType type);

// 9. Public Data (definitions)
int gBarCreatedCount   = 0; // Initialize global variable
int gBarDestroyedCount = 0; // Initialize global variable

// 10. Public functions (definitions)
bool ProcessData(uint8_t const* refData, size_t size) {
    (void)(refData);
    (void)(size);
    // Implementation of ProcessData function
    return true;
}

Bar* Bar_Create() {
    gBarCreatedCount++;
    sCurrentBarCount++;
    return (Bar*)malloc(sizeof(Bar));
}

Bar* Bar_Initialize(Bar* outBar, Foo foo, Point p) {
    ASSERT(outBar);
    ASSERT(EXAMPLE_TYPE_IS_FOO(foo));

    outBar->type = eExampleType_Bar;
    outBar->foo  = foo;
    outBar->p    = p;

    return outBar;
}

void Bar_Destroy(Bar** outBarPtr) {
    ASSERT(outBarPtr);
    ASSERT(*outBarPtr);
    free(*outBarPtr);
    *outBarPtr = NULL;

    gBarDestroyedCount++;
    sCurrentBarCount--;
}

int main() {
    TestPoint();

    Bar* bar = Bar_Initialize(Bar_Create(), (Foo){.type = eExampleType_Foo, .value = 42}, kBarInitPoint);
    ASSERT(bar);
    ASSERT(bar->type == eExampleType_Bar);
    ASSERT(gBarCreatedCount == 1);
    ASSERT(gBarDestroyedCount == 0);
    ASSERT(sCurrentBarCount == 1);

    char const* const typeName = ExampleType_ToStringType(bar->type);
    Bar_Destroy(&bar);
    if (!bar) {
        printf("%s object was successfully destroyed.\n", typeName);
    }
    ASSERT(gBarCreatedCount == 1);
    ASSERT(gBarDestroyedCount == 1);
    ASSERT(sCurrentBarCount == 0);

    return 0;
}

// 11. Private functions (definitions)
void TestPoint() {
  // ...
}

char const* ExampleType_ToStringType(ExampleType type) {
    switch (type) {
    case eExampleType_Foo:
        return kFooTypeName;
    case eExampleType_Bar:
        return kBarTypeName;
    default:
        return "Unknown";
    }
}

References

Syque's C Style/CHAPTER 7 : File Layout

NuttX documentation's C Coding Standard/File Organization

Axom documentation's Coding Guidelines/4 Header File Organization

About

Guidelines for modern C coding, including style conventions and layout organization.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages