Проверка кода компилятором
Рассмотрим ключи на примере компилятора GNU/GCC. Их достаточно много, поэтому обратим внимание только на самые важные.
Существует несколько стандартов языка, а к ним есть ещё и расширения. Вернёмся к инициализации массива. С расширениями GNU можно сделать так:
uint8_t arr[10] = { [0 ... 2] = 42, /* ... */ };
Удобно и красиво. Но данный код не скомпилируется под STM8 с проприетарным компилятором от IAR. Если вы пишете универсальную библиотеку, следует строго следовать стандарту. Используйте ключ -Wpedantic, и компилятор не пропустит отклонений.
ISO C forbids specifying range of elements to initialize [-Wpedantic]
Компилятор гибок в настройке и может проверять код на предмет спорных решений. Большую часть можно отловить, используя ключи -Wall и -Wextra. Перечислять их не будем, обратитесь к официальной документации, но для понимания ниже приведена пара примеров.
- Вы сознательно использовали неявное приведение типов или нет? В некоторых случаях это может привести к потере данных.
- Вы сравниваете переменную типа char с переменной какого-либо другого типа? Вы уверены, что он беззнаковый? Стандарт этого не гарантирует.
Другой пример. Как вы думаете, скомпилируется ли данный код?
const int x = 25;
int func() {
int x[x]; // (1)
x[17] = 0; // (2)
// return ...
}
Компилятор не выведет каких-либо предостережений. В момент инициализации (1) никакого массива ещё нет, и x
в квадратных скобках будет распознана как константа. В точке (2) область видимости будет перекрыта, т.е. x
будет массивом. Укажите ключ -Wshadow
, и компилятор выдаст сообщение вида:
declaration of 'x' shadows a global declaration [-Wshadow]
Каждое предупреждение — это потенциальный баг в прошивке. Стоит ли рисковать дорогим оборудованием, оставляя такой код? Ключ -Werror
заставляет компилятор расценивать предупреждения как ошибки компиляции. Вы не сможете собрать прошивку, пока не перепишете потенциально опасный участок. Большое количество сообщений может мешать, в таком случае воспользуйтесь ключом -fmax-errors=n
, где n
— максимальное количество отображаемых ошибок (0
= без ограничений). Ключ -Wfatal-errors
заставляет компилятор остановиться, как только он встретит первую ошибку (предупреждение), а не продолжать сборку, отлавливая все остальные.
Подведём итог: пишите код так, чтобы компилятор не выводил вам предупреждений.
-Wall -Wextra -Wshadow -Wpedantic -Werror