integer.
- You may need to be careful with structure alignments, particularly for
structures being stored on disk. Any class/structure with a
`int64_t`/`uint64_t` member will by default end up being 8-byte aligned on a
64-bit system. If you have such structures being shared on disk between
32-bit and 64-bit code, you will need to ensure that they are packed the
same on both architectures. Most compilers offer a way to alter structure
alignment. For gcc, you can use `__attribute__((packed))`. MSVC offers
`#pragma pack()` and `__declspec(align())`.
- Use the `LL` or `ULL` suffixes as needed to create 64-bit constants. For
example: >c
int64_t my_value = 0x123456789LL;
uint64_t my_mask = 3ULL << 48;
sizeof ~
Prefer `sizeof(varname)` to `sizeof(type)`.
Use `sizeof(varname)` when you take the size of a particular variable.
`sizeof(varname)` will update appropriately if someone changes the variable
type either now or later. You may use `sizeof(type)` for code unrelated to any
particular variable, such as code that manages an external or internal data
format where a variable of an appropriate C type is not convenient. >c
Struct data;
memset(&data, 0, sizeof(data));
memset(&data, 0, sizeof(Struct));
if (raw_size < sizeof(int)) {
fprintf(stderr, "compressed record not big enough for count: %ju", raw_size);
return false;
}
==============================================================================
Naming *dev-style-naming*
The most important consistency rules are those that govern naming. The style
of a name immediately informs us what sort of thing the named entity is: a
type, a variable, a function, a constant, a macro, etc., without requiring us
to search for the declaration of that entity. The pattern-matching engine in
our brains relies a great deal on these naming rules.
Naming rules are pretty arbitrary, but we feel that consistency is more
important than individual preferences in this area, so regardless of whether
you find them sensible or not, the rules are the rules.
General Naming Rules ~
Function names, variable names, and filenames should be descriptive; eschew
abbreviation.
Give as descriptive a name as possible, within reason. Do not worry about
saving horizontal space as it is far more important to make your code
immediately understandable by a new reader. Do not use abbreviations that are
ambiguous or unfamiliar to readers outside your project, and do not abbreviate
by deleting letters within a word. >c
int price_count_reader; // No abbreviation.
int num_errors; // "num" is a widespread convention.
int num_dns_connections; // Most people know what "DNS" stands for.
int n; // Meaningless.
int nerr; // Ambiguous abbreviation.
int n_comp_conns; // Ambiguous abbreviation.
int wgc_connections; // Only your group knows what this stands for.
int pc_reader; // Lots of things can be abbreviated "pc".
int cstmr_id; // Deletes internal letters.
File Names ~
Filenames should be all lowercase and can include underscores (`_`).
Use underscores to separate words. Examples of acceptable file names: >
my_useful_file.c
getline_fix.c // ✅: getline refers to the glibc function.
C files should end in `.c` and header files should end in `.h`.
Do not use filenames that already exist in `/usr/include`, such as `db.h`.
In general, make your filenames very specific. For example, use
`http_server_logs.h` rather than `logs.h`.
Type Names ~
Typedef-ed structs and enums start with a capital letter and have a capital
letter for each new word, with no underscores: `MyExcitingStruct`.
Non-Typedef-ed structs and enums are all lowercase with underscores between
words: `struct my_exciting_struct` . >c
struct my_struct {
...
};
typedef struct my_struct MyAwesomeStruct;