Поиск по сайту:

Необычные, но полезные параметры командной строки GCC — часть 2


На этой странице

  1. Включить предупреждения, на которые не распространяется -Wall
  2. Включить предупреждение о значениях с плавающей запятой при сравнении капитала.
  3. Как лучше управлять параметрами командной строки gcc
  4. Заключение

Компилятор gcc предлагает, казалось бы, бесконечный список параметров командной строки. Конечно, ни одна организация не использует их все и не имеет опыта работы со всеми из них, но есть избранная группа, которую каждый пользователь gcc должен (если не должен) знать. В то время как некоторые из них широко используются, другие немного необычны, но не менее полезны.

В этой серии статей мы сосредоточимся на некоторых из этих необычных, но полезных параметров командной строки gcc, и уже рассмотрели пару из них в части 1.

Если вы помните, в начале первой части этой серии руководств я кратко упомянул, что параметр -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;
/* ...
some code here
...
*/

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-type-parameter (только C), -Wold-style-declaration (только C), -Woverride-init, -Wsign- сравнения, -Wtype-limits, -Wuninitialized, -Wunused-parameter (только с параметром -Wunused или -Wall) и -Wunused-but-set-parameter (только с параметром -Wunused или -Wall).

Если вы хотите узнать, что делают вышеупомянутые флаги, перейдите на справочную страницу gccs.

Далее, опция -Wextra также выдает предупреждения в следующих случаях:

  • Указатель сравнивается с целым нулем с помощью <, <=, > или >=.
  • (только C++) И перечислитель, и не перечислитель появляются в условном выражении
    .
  • (только C++) Неоднозначные виртуальные базы.
  • (только C++) Подписка массива, который был объявлен
    register.
  • (только C++) Берется адрес переменной,
    объявленной регистром.
  • (только C++) Базовый класс не инициализируется в конструкторе копирования производных классов
    .

Включить предупреждение о значениях с плавающей запятой при сравнении капитала

Как вы, возможно, уже знаете, никогда не следует проверять точное равенство значений с плавающей запятой (не знал об этом — прочитайте FAQ по сравнению с плавающей запятой здесь). Но даже если вы случайно сделаете это, компилятор gcc выдаст предупреждение или ошибку? Давайте проверим:

Вот код, который сравнивает переменные с плавающей запятой с помощью оператора ==:

#include<stdio.h>

void compare(float x, float y)
{
if(x == y)
{
printf("\n EQUAL \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:

The idea behind this is that sometimes it is convenient (for the programmer) to consider floating-point values as approximations to infinitely precise real numbers. If you are doing this, then you
need to compute (by analyzing the code, or in some other way) the maximum or likely maximum error that the computation introduces, and allow for it when performing comparisons (and when producing
output, but that's a different problem). In particular, instead of testing for equality, you shouldcheck to see whether the two values have ranges that overlap; and this is done with the relational operators, so equality comparisons are probably mistaken.

Как лучше управлять параметрами командной строки gcc

Если список параметров командной строки, которые вы используете в своей команде gcc, становится больше и им трудно управлять, вы можете поместить его в текстовый файл и передать имя этого файла в качестве аргумента команде gcc. Для этого вам нужно использовать параметр командной строки @file.

Например, если следующая ваша команда gcc:

gcc -Wall -Wextra -Wfloat-equal test.c -o test

Затем вы можете поместить три параметра, связанные с предупреждениями, в файл с именем, скажем, gcc-options:

$ cat gcc-options 
-Wall -Wextra -Wfloat-equal

И ваша команда gcc становится менее загроможденной и простой в управлении:

gcc @gcc-options test.c -o test

Вот что справочная страница gcc говорит о @file:

Read command-line options from file. The options read are inserted in place of the original @file option. If file does not exist, or cannot be read, then the option will be treated literally, and not removed.

Options in file are separated by whitespace. A whitespace character may be included in an option by surrounding the entire option in either single or double quotes. Any character (including a backslash) may be included by prefixing the character to be included with a backslash. The file may itself contain additional @file options; any such options will be processed recursively.

Заключение

Итак, в этой серии руководств мы рассмотрели в общей сложности 5 необычных, но полезных параметров командной строки gcc: -save-temps, -g, -Wextra, -Wfloat-equal и @file. Потратьте время на практику каждого из них и не забудьте просмотреть все подробности, которые о них предлагает справочная страница gcc.

Вы знаете или используете другие полезные параметры командной строки gcc и хотите поделиться ими со всем миром? Все подробности оставляйте в комментариях ниже.