Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

coding-pelican/c-style-guide

Open more actions menu

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

Morty Proxy This is a proxified and sanitized view of the page, visit original site.