Declare variable in any block
Not
void test(uint8_t input) {
uint32_t b;
if (input > 3) {
return;
}
b = input;
}
But
void test(uint8_t input) {
if (input > 3) {
return;
}
uint32_t b = input;
}
For counter variable
Not
uint32_t i;
for (i = 0; i < 10; i++)
But
for (uint32_t i = 0; i < 10; i++)
Array initialization
Not
uint32_t numbers[64];
memset(numbers, 0, sizeof(numbers));
But
uint32_t numbers[64] = {0};
Structure initialization
Not
struct thing {
uint64_t index;
uint32_t counter;
};
struct thing localThing;
void initThing(void) {
memset(&localThing, 0, sizeof(localThing));
}
But
struct thing {
uint64_t index;
uint32_t counter;
};
struct thing localThing = {0};
Function input type
Not
void processAddBytesOverflow(uint8_t *bytes, uint32_t len) {
for (uint32_t i = 0; i < len; i++) {
bytes[0] += bytes[i];
}
}
But
void processAddBytesOverflow(void *input, uint32_t len) {
uint8_t *bytes = input;
for (uint32_t i = 0; i < len; i++) {
bytes[0] += bytes[i];
}
}
將輸入型別設定為 void 並在內容中重新指派
Return Type
若回傳值有「是」/「否」這種需求,建議引入 stdbool.h 函式庫,使用 true 或 false 來代替整數型態(例如 int32_t)的 1 或 0。讓程式更容易閱讀。
可以的話,建議創一個 enum 來表示複合型態的回傳型別。例如:
typedef enum growthResult {
GROWTH_RESULT_SUCCESS = 1, // 成功
GROWTH_RESULT_FAILURE_GROW_NOT_NECESSARY, // 失敗 1
GROWTH_RESULT_FAILURE_ALLOCATION_FAILED // 失敗 2
} growthResult;
Coding style
寫作習慣
程式沒人看得懂,功能再怎麼強都沒用。文章中建議使用自動格式工具(auto code formatter):clang-format。
例如要對目標 main.c 進行轉換,在終端機中敲入:
$ clang-format -style="{BasedOnStyle: llvm, IndentWidth: 4, AllowShortFunctionsOnASingleLine: None, KeepEmptyLinesAtTheStartOfBlocks: false}" "$@" -i main.c
clang-format 會將將程式依建議重新排版。但是每次都這樣敲太麻煩了。可以將 clang-format 指令以 alias 的型式建在 .bash_profie 或 .bash_rc 中:
# .bash_profile or .bash_rc
alias clang-format='clang-format -style="{BasedOnStyle: llvm, IndentWidth: 4, AllowShortFunctionsOnASingleLine: None, KeepEmptyLinesAtTheStartOfBlocks: false}" "$@"'
之後就能直接以 clang-format 進行轉換:
$ clang-format -i main.c
其中若省略掉 -i 是直接在 bash 中預覽結果,而不將轉換結果覆寫掉目標檔案。
Allocation
Not malloc bu calloc, and prevent memset