不常见但是很有用的 GCC 命令行选项（二）
gcc 调试 编译
gcc 编译器提供了几乎数不清的命令行选项列表。当然，没有人会使用过或者精通它所有的命令行选项，但是有一些命令行选项是每一个 gcc 用户都应该知道的 - 即使不是必须知道。它们中有一些很常用，其他一些不太常用，但不常用并不意味着它们的用处没前者大。


![](/data/attachment/album/201612/13/084321p0tmmzbm0x8xlcyk.jpg)


在这个系列的文章中，我们集中于一些不常用但是很有用的 gcc 命令行选项，在[第一节](/article-8025-1.html)已经讲到几个这样的命令行选项。


不知道你是否能够回想起，在这个系列教程的第一部分的开始，我简要的提到了开发者们通常用来生成警告的 `-Wall` 选项，并不包括一些特殊的警告。如果你不了解这些特殊警告，并且不知道如何生成它们，不用担心，我将在这篇文章中详细讲解关于它们所有的细节。


除此以外，这篇文章也将涉及与浮点值相关的 gcc 警告选项，以及在 gcc 命令行选项列表变得很大的时候如何更好的管理它们。


在继续之前，请记住，这个教程中的所有例子、命令和指令都已在 Ubuntu 16.04 LTS 操作系统和 gcc 5.4.0 上测试过。


### 生成 -Wall 选项不包括的警告


尽管 gcc 编译器的 `-Wall` 选项涵盖了绝大多数警告标记，依然有一些警告不能生成。为了生成它们，请使用 `-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-parameter-type` （仅针对 C 语言）
* `-Wold-style-declaration` （仅针对 C 语言）
* `-Woverride-init`
* `-Wsign-compare`
* `-Wtype-limits`
* `-Wuninitialized`
* `-Wunused-parameter` （只有和 `-Wunused` 或 `-Wall` 选项使用时才会启用）
* `-Wunused-but-set-parameter (只有和`-Wunused`或`-Wall` 选项使用时才会生成）


如果想对上面所提到的标记有更进一步的了解，请查看 [gcc 手册](https://linux.die.net/man/1/gcc)。


此外，遇到下面这些情况， `-Wextra` 选项也会生成警告：


* 一个指针和整数 `0` 进行 `<`， `<=`， `>`， 或 `>=` 比较
* （仅 C++）一个枚举类型和一个非枚举类型同时出现在一个条件表达式中
* （仅 C++）有歧义的虚拟基底
* （仅 C++）寄存器类型的数组加下标
* （仅 C++）对寄存器类型的变量进行取址
* （仅 C++）基类没有在派生类的复制构建函数中进行初始化


### 浮点值的等值比较时生成警告


你可能已经知道，浮点值不能进行确切的相等比较（如果不知道，请阅读与浮点值比较相关的 [FAQ](https://isocpp.org/wiki/faq/newbie))。但是如果你不小心这样做了， 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 手册](https://linux.die.net/man/1/gcc)关于这一选项的说明：



> 
> 这背后的想法是，有时，对程序员来说，把浮点值考虑成近似无限精确的实数是方便的。如果你这样做，那么你需要通过分析代码，或者其他方式，算出这种计算方式引入的最大或可能的最大误差，然后进行比较时（以及产生输出时，不过这是一个不同的问题）允许这个误差。特别要指出，不应该检查是否相等，而应该检查两个值是否可能出现范围重叠；这是用关系运算符来做的，所以等值比较可能是搞错了。
> 
> 
> 


### 如何更好的管理 gcc 命令行选项


如果在你使用的 gcc 命令中，命令行选项列表变得很大而且很难管理，那么你可以把它放在一个文本文件中，然后把文件名作为 gcc 命令的一个参数。之后，你必须使用 `@file` 命令行选项。


比如，下面这行是你的 gcc 命令：



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

```

然后你可以把这三个和警告相关的选项放到一个文件里，文件名叫做 `gcc-options`：



```
$ cat gcc-options&nbsp;
-Wall -Wextra -Wfloat-equal

```

这样，你的 gcc 命令会变得更加简洁并且易于管理：



```
gcc @gcc-options test.c -o test

```

下面是 gcc 手册关于 `@file` 的说明：



> 
> 从文件中读取命令行选项。读取到的选项随之被插入到原始 `@file` 选项所在的位置。如果文件不存在或者无法读取，那么这个选项就会被当成文字处理，而不会被删除。
> 
> 
> 文件中的选项以空格分隔。选项中包含空白字符的话，可以用一个由单引号或双引号包围完整选项。任何字符（包括反斜杠: '\'）均可能通过一个 '\' 前缀而包含在一个选项中。如果该文件本身包含额外的 `@file` 选项，那么它将会被递归处理。
> 
> 
> 


### 结论


在这个系列的教程中，我们一共讲解了 5 个不常见但是很有用的 gcc 命令行选项： `-Save-temps`、`-g`、 `-Wextra`、`-Wfloat-equal` 以及 `@file`。记得花时间练习使用每一个选项，同时不要忘了浏览 gcc 手册上面所提供的关于它们的全部细节。


你是否知道或使用其他像这样有用的 gcc 命令行选项，并希望把它们在全世界范围内分享？请在下面的评论区留下所有的细节。




---


via: <https://www.howtoforge.com/tutorial/uncommon-but-useful-gcc-command-line-options-2/>


作者：[Ansh](https://twitter.com/howtoforgecom) 译者：[ucasFL](https://github.com/ucasFL) 校对：[jasminepeng](https://github.com/jasminepeng)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
# Uncommon but useful GCC command line options - part 2

The gcc compiler offers a seemingly never-ending list of command line options. Of course, no body uses or has expertise on all of them, but there are a select bunch that every gcc user should - if not must - know. While some of them are commonly used, others are a bit uncommon but no less useful.

In this article series, we are focusing on some of those uncommon but useful gcc command line options, and have already covered a couple of them in the [part 1](https://www.howtoforge.com/tutorial/uncommon-but-useful-gcc-command-line-options/).

If you recall, in the beginning of the first part of this tutorial series, I briefly mentioned that the *-Wall* option that developers generally use for generating warnings doesn't cover some specific warnings. If you aren't aware of these warnings and have no idea on how to enable them, worry not, as we'll be explaining all that in detail in this article.

Aside from this, we'll also be covering a gcc warning option related to floating point variables, as well as how to better manage the gcc command line options if the list grows large.

*But before we move ahead, please keep in mind that all the examples, command, and instructions mentioned in this tutorial have been tested on Ubuntu 16.04 LTS, and the gcc version that we've used is 5.4.0.*

## Enable warnings that aren't covered by -Wall

While the *-Wall* option of the gcc compiler covers most of the warning flags, there are some that remain disabled. To enable them, use the ** -Wextra** option.

For example, take a look at the following code:

#include <stdio.h>

#include <stdlib.h>

int main()

{

int i=0;

/* ...

some code here

...

*/


if(i);

return 1;

return 0;

}

I accidentally put a semicolon after the 'if' condition. Now, when the code was compiled using the following gcc command, no warning was produced.

gcc -Wall test.c -o test

But when the -Wextra option was used:

gcc -Wall -Wextra test.c -o test

A warning was produced:

test.c: In function ‘main’:

test.c:10:8: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body]

if(i);

As clear from the warning shown above, the *-Wextra* option internally enabled the *-Wempty-body* flag, which in turned detected the suspicious code and issued the warning. Here is the complete list of warning flags enabled by this option:

-Wclobbered, -Wempty-body, -Wignored-qualifiers, -Wmissing-field-initializers, -Wmissing-parameter-type (C only), -Wold-style-declaration (C only), -Woverride-init, -Wsign-compare, -Wtype-limits, -Wuninitialized, -Wunused-parameter (only with -Wunused or -Wall), and -Wunused-but-set-parameter (only with -Wunused or -Wall).

If you want to learn what the above mentioned flags do, head to [gcc's man page](https://linux.die.net/man/1/gcc).

Moving on, the -Wextra option also issues warnings in the following cases:

- A pointer is compared against integer zero with <, <=, >, or >=
- (C++ only) An enumerator and a non-enumerator both appear in a

conditional expression. - (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared

register. - (C++ only) Taking the address of a variable that has been

declared register. - (C++ only) A base class is not initialized in a derived class's

copy constructor.

## Enable warning for floating point values in equity comparisons

As you might already know, one should never test for the exact equality of floating-point values (didn't know this - read the floating-point comparison-related FAQ [here](https://isocpp.org/wiki/faq/newbie)). But even if you accidentally do this, does the gcc compiler throw any warning or error? Let's check out:

Here's a code that compares floating point variables using == operator:

`#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;

}

And here's the gcc command (containing both -Wall and -Wextra options) used to compile this code:

gcc -Wall -Wextra test.c -o test

Sadly, the above command doesn't produce any warning related to floating point comparison. A quick look at GCC's man page reveals that there exists a dedicated option ** -Wfloat-equal** that should be used in these scenarios.

Here's the command containing this option:

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

And following is the output it produced:

test.c: In function ‘compare’:

test.c:5:10: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]

if(x == y)

So as you can see in the output above, the -Wfloat-equal option forced gcc to produce warning related to floating comparison.

Here is what [the gcc man page](https://linux.die.net/man/1/gcc) says about this option:

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.

## How to better manage gcc command line options

If the list of command line options that you are using in your gcc command is becoming larger and difficult to manage, then you can put it in a text file, and pass that file's name as an argument to the gcc command. For this, you'll have to use the ** @file** command line option.

For example, if following is your gcc command:

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

Then you can put the three warnings-related options in a file named, say 'gcc-options' :

$ cat gcc-options

-Wall -Wextra -Wfloat-equal

And your gcc command becomes less cluttered and easy to manage:

gcc @gcc-options test.c -o test

Here's what the gcc man page says about @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.

## Conclusion

So we covered a total of 5 uncommon but useful gcc command line options in this tutorial series: -save-temps, -g, -Wextra, -Wfloat-equal, and @file. Do spend time practicing each of them and don't forget to go through all the details that the gcc man page offers about them.

Do you know or use other such useful gcc command line options, and want to share them with the world? Leave all the details in comments below.