Проверка кода компилятором

Рассмотрим ключи на примере компилятора 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. Перечислять их не будем, обратитесь к официальной документации, но для понимания ниже приведена пара примеров.

  1. Вы сознательно использовали неявное приведение типов или нет? В некоторых случаях это может привести к потере данных.
  2. Вы сравниваете переменную типа 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

Изменено: