This is my own styleguide, meant mainly for me. You don’t have to agree or follow anything that’s written here.
The opening brace of a function should be placed on the same line as the function definition, separated by a space from the class definition. The closing brace should be placed on the line following the last line of the function.
int main() {
// do something
return 0;
}
Braces should not be used for a function if you are only declaring the signature.
int main();
Always forward-declare functions that you MAY need later at the start of a file. It takes a few seconds, and saves you some time later.
Always use extern when forward-declaring a function that is NOT defined in the same file. This informs the reader that the function is defined somewhere else.
Always use extern when forward-declaring a variable in C++, as just T variable; may initialise it.
Identation should be done using TABS.
Files should be formatted with UTF-8 and LF, regardless of operating system. Only exception is Powershell scripts, which should use UTF-16+BOM and CRLF.
Avoid smart pointers unless:
Store pointers as:
unsigned char*: for pointer arithmeticvoid*: for storage, or function input/output (or pointer arithmetic, on toolchains and platforms where sizeof(void) == 1, although this is discouraged)T*: function input/output, internal type conversions, storage, or pointer arithmeticAlways use unsigned char* instead of char* (or signed char*, if you for some reason need it to be signed).
All output binaries should be as position-independent as possible, regardless of usecase. (Excluding kernel-level programming, or binaries where size is a priority)
On Linux, position-independent binaries should be made with the use of -fPIC or -fPIE -pie flags for g++.
Debug builds should be built with the following arguments:
g++ -g -O1 -fPIE -pie or g++ -g -O1 -fPIC -fsanitize=undefined -Wshadowg++ -g -O1 -fno-common, -Wl,--high-entropy-va -fsanitize=undefined -WshadowProduction builds should be built with the following arguments:
-O3/-Ofast, -fstack-protector-strong/-fstack-protector-all, -fPIE -pie/-fPIC, -fno-delete-null-pointer-checks, -Wtrampolines, -D_FORTIFY_SOURCE=2/-D_FORTIFY_SOURCE=3, -Werror=shadow, -Wextra, -fwrapv, -fstack-clash-protection, -Werror=return-type, -fno-strict-aliasing, -fno-strict-overflow-O3/-Ofast, -fstack-protector-strong/-fstack-protector-all, -fno-delete-null-pointer-checks, -Wtrampolines, -D_FORTIFY_SOURCE=2/-D_FORTIFY_SOURCE=3, -Werror=shadow, -Wextra, -fwrapv, -fstack-clash-protection, -Werror=return-type, -fno-strict-aliasing, -fno-strict-overflow[!CAUTION]
Please note that
-Ofastintroduces aggressive optimization that my slightly alter floating point math, and may break some things/
We also recommend the following flags, to forcefully prevent dangerous behaviour, as well as unused code:
-Werror=uninitialized-Werror=maybe-uninitialized-Werror=use-after-free-Werror=use-after-scope-Werror=free-nonheap-object-Werror=double-promotion-Wmisleading-indentation-Werror=unused-parameter-Werror=unused-variable-Werror=sequence-point-Werror=stringop-overread-Werror=format-security-Werror=array-bounds-Wstringop-overflow[!TIP]
With the following flags, the presence of any unused parameters will throw an error. Use the following macro to suppress said errors:
#define UNUSED(x) ((void)(x))Example:
void output(int number, int number2) { UNUSED(number2); std::cout << number; }However, only do this if you plan on shortly starting to use the parameter in question, or have no choice but to keep it.
For builds making excessive use of alloca(), consider giving them a bigger stack size.
Naming conventions that should be used:
_t)Temporary variables must start with an underscore, or end in _tmp.
For the sake of reproducibility, only use compilers that are part of the GNU compiler set (gcc/g++/ld/nasm).
UB (Undefined Behaviour) is a scary topic for everyone.
You shouldn’t avoid it. You should understand what happens when you run different mechanisms that cause ‘UB’, and you should avoid behaviour that is unpredictable/unexpected/error-prone/unreproducible.
Understanding the compiler is always better than fearing the compiler.