Skip to content
Cong edited this page Jan 23, 2015 · 2 revisions

There are no hard and fast rules; just try to follow the style of the surrounding code.

The coding style in the C-Dogs SDL codebase is very inconsistent and evolving; clean code is nice but that has been a lower priority.

Code sample:

/* LICENSE TEXT */
#include "foo.h"

#include <stdlib.h>

#include "bar.h"

void FooInit(Foo *f)
{
    // ...
}
void FooTerminate(Foo *f)
{
    // ...
}

static void HelpMe(void);
void FooFrobnicate(Foo *f, const Defibrillator *d)
{
    const int w = 3;
    for (int i = 0; i < d->bar; i++)
    {
        if (i == w)
        {
            Frobnicate();
        }
    }
    HelpMe();
}
static void HelpMe(void)
{
    printf("Uh oh\n");
}

General guidelines

  • C99
    • Some non-standard features are ok as long as they are widely supported, e.g. #pragma once
  • Try to use self-contained modules
  • Try to avoid globals; if necessary name them with a g prefix e.g. gFoo
  • goto is not verboten; the goto cleanup idiom is ok, don't panic
  • Prefer dynamically allocated strings over char arrays; use the latter for simplicity, if speed is critical and the max size is known and likely won't ever change. There's the CDOGS_FILENAME_MAX and CDOGS_PATH_MAX constants for filesystem-related char arrays.
  • Try to avoid #ifdefs; if necessary place them in sys_specifics.h or sys_config.h
  • Use const wherever possible, even for values - this discourages reusing variables

Modules

Modules are the preferred way of adding new functionality. Modules are defined using a typed struct with functions that are prefixed with the struct name, and used in an OOP-like manner.

  • A module Foo should be defined in a file foo.h and implemented in a file foo.c
  • In the header, define a typedef struct { ... } Foo;
  • All functions for the module should have a Foo * or const Foo * as the first argument and be prefixed with Foo, e.g. void FooFrob(Foo *f, int frob) or int FooGetBaz(const Foo *f)
  • Unless the module is trivial or POD-like (e.g. color), it should have a void FooInit(Foo *f) and void FooTerminate(Foo *f)
  • The init function should initialise all members and not depend on previous state. Assume that the module has not been initialised.
  • The terminate function should always work (e.g. double-terminate)

Naming

  • PascalCase for functions, types and "public" members
  • camelCase for variables and "private" members
  • Prefix a g for global variables e.g. gFooBar
  • Leave on caps for acronyms e.g. HTTPReader

Standard utilities

Like many C projects, C-Dogs SDL has a collection of thin wrappers around standard functions and project-specific idioms that should be followed. This section may be subject to change as the project evolves.

  • CASSERT is a macro that performs assert - it gets compiled out in release builds, but in debug it halts the program with a message if the check fails.
  • Use the CMALLOC/CCALLOC/CREALLOC/CFREE/CSTRDUP macros for memory operations
  • Use the CArray type for resizeable arrays