Skip to content

Latest commit

 

History

History
248 lines (195 loc) · 12.1 KB

README.md

File metadata and controls

248 lines (195 loc) · 12.1 KB

MaiHD's C/C++ programming style

Notes

  • I'm still learning and practicing for better as C/C++. Ideas and opinions may wrong.
  • Mai English is not good, if You find the typos, wrong words and wrong meanings, please help!
  • Some Mai projects will follow its own style (but not too different from this style) for special reasons. Ex: vectormath
  • I use other projects style guide for thoses projects. It help me learn the others, and new stuffs, why not?
  • Because I will use Zig and Beef for some future projects, each languages has its own styles, I will follow the style, but the heart of priciple will be same: Simply make the job done!
  • Based on the important of the section, I will bring it first the most important, last section is the least important.
  • Note: this project can be consider as a R&D for Mai personal work, you can find some ideas in docs folder.

Table of Contents

  1. Inventing on Principles
  2. Workflow
  3. Programming Languages, Standards, Spirits
  4. Naming convention
  5. Naming convention 2
  6. Naming cheatsheet
  7. Types
  8. Scoping
  9. File layout
  10. Project architecture
  11. Build system
  12. Tooling
  13. License
  14. Additional Resources

Inventing on Principles

  • Do what matter to get the job done!
  • Immediate feedback
  • What you see is what you get: WYSIWYG
  • Simple, open, immediate, low level, debug/discipline
    • The new SOLID principles
    • Keep it simple and small, for product
    • Keep it slow and steady, for development product
    • Open mind to the problem
    • Open data for the program to do what it needs to do
    • Open source for people
    • Open the black box practice
    • Immediate feedback, also know as low-latency iterations
    • Inventing on principles (recursive until there are no principles needed)
    • Incrementally development
    • Low level for abstractions
    • Love and passion
    • Learn the hard way
    • Debug easily, focus on development, and use better tools
    • Discipline, donot break the rules of the project (each project have each own rules)
    • All principles support each others
  • Self-reliance, mindfulness
    • "What I cannot create, I cannot understand" - Richard Feynman
    • First, use it; second, attempt to create it with simple implementation; third, use it better
    • Stay focused on the project, and the project only, right now!
  • Zen creating & living!

Workflow

Working on it.

Programming Languages, Standards, Spirits

  • Use C99 and C++11.
    • Update 5/6/2024: C11 (C17 just a fix bugs version of C11) and C++17 widely support now (MSCV, Clang, GCC). But without appreciate reasons, you should avoid thoses features.
  • Follow spririts of C, simple and easy to read.
  • #pragma once is widely supported now. Use it prefer to header guards.
  • Use unix encoding.
  • Content file only support ASCII. Donot use utf8 file format.
  • Prefer code that both compile on C and C++
  • Some features can be support both on C and C++ with extensions, define a keyword with preprocessor.
  • Preprocessor is not bad. Duck typing is not bad. Un-tested code is bad. Write the code are needed to be written, test and proof that code work, are the good resolutions for thoses problems.
  • Prefer clang (and family like zig cc) for toolchains, feel free to use extensions if project is clang-only.
  • Deep dive in ProgLang.md

Naming convention

Please know that naming convention in C/C++ is not forcing in variant type of projects. Mean that naming for readable more important than conventions.

  • Typename: PascalCase. Ex: Texture, Shader, Image, ...
  • Function name: PascalCase, ModuleName_FunctionName. Ex: ArrayPush, Texture_New, ...
  • Enums, constants: ALL_CAPS_CASE. Ex: PI, NULL, PIXEL_RGBA, ...
  • Enums only: TypeName_MemberName. Ex: JsonError_OutOfMemory, FileAccess_ReadWrite, ...
  • Variables, fields, paramaters: camelCase. Ex: texture.width, texture.height, ...
  • Custom keywords: __snake_case. Ex: __enum_type, __default_init, __defer, __typename, __scope, ...
  • Reuse keywords instead of define new: constexpr, __forceinline, alignas, alignof, offsetof, container_of, __vectorcall, ...

Naming convention 2

This convention is more common in C/C++. So I accept this.

  • Typename: PascalCase. Ex: Texture, Shader, Image, ...
  • Module name: snake_case. Ex: vec2, mat4, ...
  • Function name: snake_case, module_name_function_name. Ex: array_push, texture_new, ...
  • Enums, constants: ALL_CAPS_CASE. Ex: PI, NULL, PIXEL_RGBA, ...
  • Enums only: TypeName_MemberName. Ex: JsonError_OutOfMemory, FileAccess_ReadWrite, ...
  • Variables, fields, paramaters: snake_case. Ex: texture.width, texture.height, ...
  • Custom keywords: __snake_case. Ex: __enum_type, __default_init, __defer, __typename, __scope, ...
  • Reuse keywords instead of define new: constexpr, __forceinline, alignas, alignof, offsetof, container_of, __vectorcall, ...

Naming cheatsheet

This section need a database, because naming is enormous and must have only one meaning.

  • Init/Deinit: for initialization/deinitialization, no return pointer
  • Create/Destroy: create new memory, init/deinit, and return pointer (object)
  • Alloc/Free: actually request memory from system
  • Acquire/Release: get memory (also resources) from a buffer/arena/allocator (not return to system when call release)

Types

  • Integer type: use specified width integers for data structures, int for parameters, return types, local variables.

    • int8_t/uint8_t instead of char/unsigned char in data structures.
    • int16_t/uint16_t instead of short/unsigned short in data structures.
    • int32_t/uint32_t instead of int/unsigned int in data structures.
    • int64_t/uint64_t instead of long long/unsigned long long (long is 32-bit on Windows) in data structures.
    • In some cases, there will need float32_t/float64_t instead of float/double
    • Specified width integers in ensure the data structures are same size independent on platforms.
    • int and familiar is prefer because this help compiler do optimization. (rarely use, only helpful for uncommon platforms)
  • float prefer to double, only use double when needed.

  • (C only) Generic types: Array(T), Buffer(T), HashTable(T). Avoid T* for multiple values. Should add prefix T.

  • T* mean pass-by-reference, it mustnot be NULL.

  • Use value semantic, pass-by-value. For performance reason, make sure use const to prevent evil work on data structures.

  • Typedef struct, enum, union. Prefer explicit aligned data structures.

    typedef struct ALIGNAS(vec3, 16) // ALIGNAS is crossplatform of __declspec(align)
    {
        float x, y, z;
    } vec3;
    
    typedef enum WindowFlags
    {
        ...
    } WindowFlags;
    
    typedef union Handle
    {
        void*       onWindows;
        uint64_t    onUnix;
    } Handle;
  • Plain-old data prefer to C++ struct.

  • Avoid use C++ namespace, because C doesnot support. So avoid enum class too.

  • Extended primitive types: vectors and matrices (for graphics and game programming)

    • vec2, vec3, vec4: single precision floating-point vectors (32-bit per component)
    • ivec2, ivec3, ivec4: signed integer vectors (32-bit per component)
    • uvec2, uvec4, uvec4: unsigned interger vectors (32-bit per component)
    • mat2, mat3, mat4: single precision floating-point matrices (32-bit per component)
    • imat2, imat3, imat4: signed integer vectors (32-bit per component)
    • umat2, umat3, umat4: unsigned integer vectors (32-bit per component)
    • bool2, bool3, bool4: one-byte wide component (1-bit per component)
    • <std_wided_prim>x<components>_t (uint32x4_t, int32x4_t, float32x4_t, ...): SIMD primitive types

Scoping

  • Single { } in one line, add newline after it.
  • But all definition of macro when have multiple lines.

File layout

  • File Header (beginning of the file, not to confusing with .h files)

    • Optional meta information, grouping by a block of coments
    • Pragma, header guards, compiler/linker options
    • Include all needed dependencies
    • Declaration of all types
    • Declaration of all functions/macros. But donot declare main.
  • File Body

    • Definitions of all types
    • Definitions of all functions
  • File Footer

    • An optional end-of-file mark. Ex: //! EOF
    • Should end with a newline, some compilers need this (gcc family)
  • Grouping

    • Functions and types declaration should be grouping
    • Functions and types need to align by columm, easy to find return-type, function name
    • Seperate functions, types declaration group with 1 empty line
    • Separate functions, types define with 2 empty lines

Function

  • Grouping chunk by work, what to do
  • Prefer clear, readable code
  • Prefer pure function if available
  • Avoid declare one line variables for pointer type (missing *)
  • Can use 2 newlines to seperating big chunk of code

Project architecture

  • Filename: prefer PascalCase. Maybe have Namespace_ prefix. Ex: Example_HelloWorld.c
  • Libraries/modules should be small. The smallest size of a library is a single header file. The smallest size of a module is a function.
  • Prefer test of module, usage of module. Unit tests should help, but not always.
  • Should have an real-life application come with it.
  • Everything should have been maintaining, so the place of VCS.
  • Self-reliance, so less dependencies. Add and use with care. Even standard library (see examples/free_runtime_1 for more details).

Build system

  • Prefer premake over cmake
  • But knowing cmake can be help
  • Base knowlege of gmake/VisualStudio always needed
  • Some incremental build systems like: ninja, FASTBuild,... Should only use when needed
  • gmake maybe best fit for many projects, counting cross-platforms
  • Sometime build.bat is all I need

Tooling (helpful and need to learn)

  • Clang and LLVM, and families
  • Clang Static Analyzer
  • Clang Format
  • Clang Tidy
  • Clang AST dump (for bindgen and preprocessing)
  • Undefined behavior sanitizer (all compilers)
  • Memory sanitizer (all compilers)
  • Thread sanitizer?
  • Tracy Profiler
  • Platform's native profiler
  • VSCode clangd (LSP for coding C/C++ with VSCode, better than VSCode Intellisense, also support swizzle syntax for vector primitives)
    • Note (11/03/2024): clangd is extremely using too much resources (RAM, CPU) when project have large header files (commonly with single header file libraries)
  • Visual Studio and helpers (not only compiler and code editor part)

License

Why you need a license for coding style. Copyright MaiHD @ Heart and Head.

Additional Resources

This section is a resources to other styles that help me through time, and it's worth to findout. It's also proved production-ready, inuse by many products, companies. (You will find its' gamedev-oriented).