Библиотека сайта rus-linux.net
Малоизвестные полезные параметры компилятора GCC - часть 2
Оригинал: Uncommon but useful GCC command line options - part 2
Автор: Himanshu Arora
Дата публикации: 1 декабря 2016 г.
Перевод: А.Панин
Дата перевода: 8 февраля 2017 г.
Компилятор GCC поддерживает на первый взгляд бесконечное количество параметров командной строки. Конечно же, никто не использует и не изучает все эти параметры в процессе работы над своим программным обеспечением, но существует ряд параметров, о которых должен, а может быть и обязан знать каждый разработчик. Некоторые из этих параметров могут использоваться достаточно часто, другие - от случая к случаю, что, впрочем, не делает их менее полезными.
В рамках данной серии статей мы рассматриваем некоторые из этих малоизвестных, но полезных параметров командной строки компилятора GCC и уже обсудили пару таких параметров в первой статье.
Если вы помните, в начале первой статьи серии я кратко упоминал о том, что параметр -Wall, который обычно используется разработчиками для генерации предупреждений, не позволяет генерировать некоторые специфические предупреждения. Если вы никогда не слышали об этих предупреждениях и методике их активации, вы можете не волноваться, так как мы подробно обсудим их в рамках данной статьи.
Кроме того, мы также обсудим параметры командной строки компилятора GCC для вывода предупреждений, связанных с переменными с плавающей точкой, а также обратим внимание на оптимальную методику работы с большим количеством параметров командной строки компилятора GCC.
Но перед тем, как перейти к рассмотрению обозначенных выше вопросов, следует упомянуть о том, что все примеры, команды и инструкции из данной статьи были протестированы в системе Ubuntu 16.04 LTS с компилятором GCC версии 5.4.0.
Активация вывода предупреждений, не связанных с параметром -Wall
Хотя параметр командной строки -Wall и сообщает компилятору GCC о необходимости вывода подавляющего большинства предупреждений, некоторые предупреждения не выводятся даже при использовании данного параметра. Для их вывода следует использовать параметр -Wextra.
В качестве примера предлагаю рассмотреть следующий код:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i=0;
/* ...
основной код
...
*/
if(i);
return 1;
return 0;
}
Я случайно разместил символ точки с запятой после условной инструкции if. При последующей компиляции кода с помощью приведенной ниже команды компилятор GCC не выведет каких-либо предупреждений:
gcc -Wall test.c -o test
А теперь рассмотрим случай использования параметра -Wextra:
gcc -Wall -Wextra test.c -o test
В этом случае будет выведено аналогичное предупреждение:
test.c: In function ‘main’: test.c:10:8: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] if(i);
Из приведенного выше текста предупреждения очевидно, что использование параметра командной строки -Wextra привело к активации флага компилятора -Wempty-body, в результате чего был выявлен подозрительный фрагмент кода и выведено соответствующее предупреждение. А это полный список флагов предупреждений, активируемых с помощью рассматриваемого параметра командной строки: -Wclobbered, -Wempty-body, -Wignored-qualifiers, -Wmissing-field-initializers, -Wmissing-parameter-type (только для языка C), -Wold-style-declaration (только для языка C), -Woverride-init, -Wsign-compare, -Wtype-limits, -Wuninitialized, -Wunused-parameter (только при использовании с -Wunused или -Wall) и -Wunused-but-set-parameter (только при использовании с -Wunused или -Wall).
Если вас интересуют подробные описания упомянутых флагов, вы можете обратиться к .
Кроме того, параметр командной строки -Wextra позволяет компилятору выводить предупреждения в следующих случаях:
- Указатель сравнивается с целочисленным нулевым значением с помощью оператора <, <=, > или >=.
- Значения из перечисления и не из перечисления встречаются в одной условной инструкции (только в C++).
- Отсутствие виртуального наследования от виртуального базового класса (только в C++).
- Доступ к элементам регистрового массива (только в C++).
- Получение адреса регистровой переменной (только в C++).
- Отсутствие инициализации базового класса в рамках конструктора копирования наследуемого класса (только в C++).
Активация предупреждений, связанных со сравнениями значений с плавающей точкой
Вы можете знать о том, что никогда нельзя осуществлять проверку равенства значений с плавающей точкой (если вы не слышали об этом, вам стоит почитать ). Но если вы случайно осуществите данную операцию, выведет ли компилятор GCC предупреждение или даже сообщение об ошибке? Давайте проверим.
Это код, в котором осуществляется проверка равенства значений переменных с плавающей точкой с помощью оператора ==:
#include <stdio.h>
void compare(float x, float y)
{
if(x == y)
{
printf("\n РАВНЫ \n");
}
}
int main(void)
{
compare(1.234, 1.56789);
return 0;
}
А это команда компиляции данного кода с помощью компилятора GCC (содержащая как параметр -Wall, так и параметр -Wextra):
gcc -Wall -Wextra test.c -o test
К сожалению, в процессе исполнения данной команды не будет выведено каких-либо предупреждений, связанных со сравнением значений с плавающей точкой. Быстрый просмотр страницы руководства GCC позволяет обнаружить наличие отдельного параметра командной строки -Wfloat-equal, который должен использоваться в подобных сценариях.
А это команда с данным параметром:
gcc -Wall -Wextra -Wfloat-equal test.c -o test
Данная команда позволяет сгенерировать аналогичный вывод:
test.c: In function ‘compare’: test.c:5:10: warning: comparing floating point with == or != is unsafe [-Wfloat-equal] if(x == y)
Как несложно обнаружить, параметр -Wfloat-equal сообщает компилятору GCC о необходимости генерации предупреждения, связанного со сравнением чисел с плавающей точкой.
А это выдержка из описания данного параметра на :
Данная операция нередко используется по той причине, что программисту удобнее считать значения с плавающей точкой бесконечно точными аппроксимацями дробных чисел. Если вы также прибегаете к ней, вам придется вычислить (путем анализа кода или каким-либо другим образом) максимальную или возможную максимальную погрешность расчета и учесть ее в процессе сравнения значений (а также их вывода, но это уже другая операция). По сути, вместо установления равенства значений вам придется установить, пересекаются ли диапазоны этих двух значений; а для этой цели должны использоваться операторы сравнения, поэтому использование оператора равенства является, скорее всего, плохой практикой.
Оптимальная работа с параметрами командной строки компилятора GCC
Если количество параметров командной строки компилятора GCC в вашем проекте стало настолько большим, что вам неудобно ими управлять, вы можете разместить эти параметры в текстовом файле и передать компилятору имя этого текстового файла в качестве параметра командной строки. Для этой цели должен использоваться специальный параметр командной строки @file.
Например, если ваша команда компиляции выглядит следующим образом:
gcc -Wall -Wextra -Wfloat-equal test.c -o test
То вы можете разместить три связанных с выводом предупреждений параметра в файле с именем, таким, как gcc-options:
$ cat gcc-options -Wall -Wextra -Wfloat-equal
После чего ваша команда компиляции станет более простой и доступной для редактирования:
gcc @gcc-options test.c -o test
А это выдержка из описания параметра @file со страницы руководства компилятора GCC:
Чтение параметров командной строки из файла. Параметры читаются и подставляются вместо параметра @file. Если файла с переданным именем не существует или этот файл не может быть прочитан, параметр будет обработан таким же образом, как и все другие параметры, а не удален.
Параметры в файле должны разделяться с помощью символов пробелов. Символ пробела может быть включен в состав параметра путем помещения этого параметра в одинарные или двойные кавычки. Любой символ (включая обратный слэш) может быть включен в состав параметра путем помещения перед этим символом обратного слэша. Сам файл может содержать дополнительные параметры @file; все эти параметры будут рекурсивно обрабатываться.
Заключение
На данный момент мы рассмотрели пять малоизвестных полезных параметров компилятора GCC: -save-temps, -g, -Wextra, -Wfloat-equal и @file. Потратьте немного своего времени на их испытание и не забудьте прочитать описание каждого из них на странице руководства компилятора GCC.
Вам знакомы другие подобные параметры командной строки компилятора GCC и вы желаете рассказать о них? Вы можете разместить любую информацию об этих параметрах в разделе комментариев.
