An Introduction to GCC - 3 Compilation options (编译选项)
for the GNU Compilers gcc
and g++
Brian Gough
Foreword by Richard M. Stallman
3 Compilation options (编译选项)
This chapter describes other commonly-used compiler options available in GCC. These options control features such as the search paths used for locating libraries and include files, the use of additional warnings and diagnostics, preprocessor macros and C language dialects.
本章介绍 GCC 中的其他常用编译器选项。这些选项控制编译器的各种特征,如用于定位库和 include 文件的搜索路径,使用附加的警告和诊断,预处理宏和 C 语言的方言。
dialect [ˈdaɪəlekt]:n. 方言,土话,同源语,行话,个人用语特征 adj. 方言的
3.1 Setting search paths (设置搜索路径)
In the last chapter, we saw how to link to a program with functions in the C math library libm.a
, using the short-cut option -lm
and the header file math.h
.
在上一章,我们看到怎样使用短选项 -lm
和头文件 math.h
把 C 数学库 libm.a
中的函数链接到程序中。
A common problem when compiling a program using library header files is the error:
在编译用到库的程序时,常碰到的一个问题是报 include 的头文件有错误:
FILE.h: No such file or directory
This occurs if a header file is not present in the standard include file directories used by gcc
. A similar problem can occur for libraries:
如果头文件不在 GCC 用到的标准 include 文件路径中,就会报这样的错。对库而言,类似的问题如下:
/usr/bin/ld: cannot find library
This happens if a library used for linking is not present in the standard library directories used by gcc
.
如果链接时用到的库不在 GCC 用到的标准库目录中,就会报这样的错。
By default, gcc
searches the following directories for header files:
默认情况下,gcc
在下面目录中搜索头文件:
/usr/local/include/
/usr/include/
and the following directories for libraries:
在下面目录中搜索库:
/usr/local/lib/
/usr/lib/
The list of directories for header files is often referred to as the include path
, and the list of directories for libraries as the library search path
or link path
.
搜索头文件的目录列表常被称为 include path
,而搜索库的目录列表被称为 library search path
or link path
。
The directories on these paths are searched in order, from first to last in the two lists above. [6] For example, a header file found in /usr/local/include
takes precedence over a file with the same name in /usr/include
. Similarly, a library found in /usr/local/lib
takes precedence over a library with the same name in /usr/lib
.
在这些路径中的目录是按次序搜索的,在上面的两个列表中从第一个到最后一个。例如,/usr/local/include
中找到的头文件优先于 /usr/include
中的同名文件。类似的,/usr/local/lib
中找到的库优先于 /usr/lib
中的同名库。
When additional libraries are installed in other directories it is necessary to extend the search paths, in order for the libraries to be found. The compiler options -I
and -L
add new directories to the beginning of the include path and library search path respectively.
当有其他库被安装到另外的目录中,为了能按序找到这些库,需要扩展搜索路径。编译器选项 -I
和 -L
用于把新目录添加到各自的 include 路径和库搜索路径的头上。
[6] 默认的搜索路径也可以包括其他依赖于系统或指定位置的目录,和 GCC 在自身安装时的目录。例如,在 64 位平台上,附加的 lib64
目录也可以是默认被搜索的。
precedence [ˈpresɪdəns]:n. 优先,居先
3.1.1 Search path example (搜索路径例子)
The following example program uses a library that might be installed as an additional package on a system – the GNU Database Management Library (GDBM). The GDBM Library stores key-value pairs in a DBM file, a type of data file which allows values to be stored and indexed by a key
(an arbitrary sequence of characters). Here is the example program dbmain.c
, which creates a DBM file containing a key testkey
with the value testvalue
:
下面的例子程序用到一个库,该库作为附加软件包可能已经被安装到系统中 – GNU 数据管理库 (GNU Database Management Library,GDBM)。GDBM 库在 DBM 文件中存储键-值对 (key-value pair),DBM 文件是一种存储值 (value),而用键 (key,即任意序列的字符) 来索引的文件。下面是一个例子程序,dbmain.c
,它创建了一个 DBM 文件,包含 testkey
的键及对应的值 testvalue
:
#include <stdio.h>
#include <gdbm.h>
int
main (void)
{
GDBM_FILE dbf;
datum key = { "testkey", 7 }; /* key, length */
datum value = { "testvalue", 9 }; /* value, length */
printf ("Storing key-value pair... ");
dbf = gdbm_open ("test", 0, GDBM_NEWDB, 0644, 0);
gdbm_store (dbf, key, value, GDBM_INSERT);
gdbm_close (dbf);
printf ("done.\n");
return 0;
}
The program uses the header file gdbm.h
and the library libgdbm.a
. If the library has been installed in the default location of /usr/local/lib
, with the header file in /usr/local/include
, then the program can be compiled with the following simple command:
该程序用到头文件 gdbm.h
和库 libgdbm.a
。如果库已经被安装到 /usr/local/lib
的默认位置,头文件也在 /usr/local/include
,那么该程序可以用下面的简单命令来编译:
$ gcc -Wall dbmain.c -lgdbm
Both these directories are part of the default gcc
include and link paths.
这些目录都属于 gcc
默认的 include 路径和链接路径。
However, if GDBM has been installed in a different location, trying to compile the program will give the following error:
然而,如果 GDBM 被安装到不同位置,试图用同样命令编译该程序,会报下面的错:
$ gcc -Wall dbmain.c -lgdbm
dbmain.c:1: gdbm.h: No such file or directory
For example, if version 1.8.3 of the GDBM package is installed under the directory /opt/gdbm-1.8.3
the location of the header file would be,
例如,如果 1.8.3 版本的 GDBM 软件包被安装在目录 /opt/gdbm-1.8.3
目录下,头文件的位置就会在
/opt/gdbm-1.8.3/include/gdbm.h
which is not part of the default gcc
include path. Adding the appropriate directory to the include path with the command-line option -I
allows the program to be compiled, but not linked:
该目录不属于 gcc
默认 include 路径。用命令行选项 -I
添加相应目录到 include 路径中,这样该程序就能编译了,但还是链接失败:
$ gcc -Wall -I/opt/gdbm-1.8.3/include dbmain.c -lgdbm
/usr/bin/ld: cannot find -lgdbm
collect2: ld returned 1 exit status
The directory containing the library is still missing from the link path. It can be added to the link path using the following option:
这是因为包含该库的目录还不在链接路径中。用下面的选项可以把库的路径添加到链接路径中去:
-L/opt/gdbm-1.8.3/lib/
The following command line allows the program to be compiled and linked:
下面的命令行可以使程序成功的编译和链接:
$ gcc -Wall -I/opt/gdbm-1.8.3/include
-L/opt/gdbm-1.8.3/lib dbmain.c -lgdbm
This produces the final executable linked to the GDBM library. Before seeing how to run this executable we will take a brief look at the environment variables that affect the -I
and -L
options.
这就生成了链接到 GDBM 库的最终的可执行文件。在看怎样运行该可执行文件以前,让我们简略地看一下影响 -I
和 -L
选项的环境变量。
Note that you should never place the absolute paths of header files in #include
statements in your source code, as this will prevent the program from compiling on other systems. The -I
option or the INCLUDE_PATH
variable described below should always be used to set the include path for header files.
注意,你不应该在源代码中的 #include
语句中放入头文件的绝对路径,因为这会让该程序不能在其他系统上编译。-I
选项或下面就要介绍的 INCLUDE_PATH
变量用来设置头文件的 include 路径
3.1.2 Environment variables (环境变量)
The search paths for header files and libraries can also be controlled through environment variables in the shell. These may be set automatically for each session using the appropriate login file, such as .bash_profile
.
通过 shell 中的环境变量可以控制头文件和库的搜索路径。可以在每次开始 shell 会话的相应登录文件中,比如 .bash_profile
,自动地设置它们。
Additional directories can be added to the include path using the environment variable C_INCLUDE_PATH
(for C header files) or CPLUS_INCLUDE_PATH
(for C++ header files). For example, the following commands will add /opt/gdbm-1.8.3/include
to the include path when compiling C programs:
可以使用环境变量 C_INCLUDE_PATH
(针对 C 的头文件) 或 CPP_INCLUDE_PATH
(针对 C++ 的头文件) 把其他目录添加到 include 路径中。例如,当编译 C 程序时,下面的命令会把 /opt/gdbm-1.8.3/include
添加到 include 路径中:
$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
$ export C_INCLUDE_PATH
This directory will be searched after any directories specified on the command line with the option -I
, and before the standard default directories /usr/local/include
and /usr/include
. The shell command export
is needed to make the environment variable available to programs outside the shell itself, such as the compiler – it is only needed once for each variable in each shell session, and can also be set in the appropriate login file.
该目录将在命令行上用选项 -I
指定的任何目录之后,但在标准默认目录 /usr/local/include
和 /usr/include
之前被搜索。Shell 命令 export
是必要的,以便 shell 以外的程序也能获得该环境变量,比如像编译器 – 对每一次 shell 会话的每一个变量来说,只需要设一次,也可以在相应的登录文件中设置。
Similarly, additional directories can be added to the link path using the environment variable LIBRARY_PATH
. For example, the following commands will add /opt/gdbm-1.8.3/lib
to the link path:
类似的,使用环境变量 LIBRARY_PATH
可以把另外的目录添加到链接路径中去。例如,下面的命令会把 /opt/gdbm-1.8.3/lib
添加到链接路径中:
$ LIBRARY_PATH=/opt/gdbm-1.8.3/lib
$ export LIBRARY_PATH
This directory will be searched after any directories specified on the command line with the option -L
, and before the standard default directories /usr/local/lib
and /usr/lib
.
该目录将在命令行上用选项 -L
指定的任何目录之后,但在标准默认目录 /usr/local/lib
和 /usr/lib
之前被搜索。
With the environment variable settings given above the program dbmain.c
can be compiled without the -I
and -L
options,
环境变量被设置好以后,上面的程序 dbmain.c
可以不用带 -I
和 -L
选项就能成功被编译,
$ gcc -Wall dbmain.c -lgdbm
because the default paths now use the directories specified in the environment variables C_INCLUDE_PATH
and LIBRARY_PATH
.
因为现在默认路径包括了在环境变量 C_INCLUDE_PATH
和 LIBRARY_PATH
中指定的目录。
3.1.3 Extended search paths (扩展搜索路径)
Following the standard Unix convention for search paths, several directories can be specified together in an environment variable as a colon separated list:
遵循标准 Unix 搜索路径的规范,搜索目录可以在环境变量中用冒号分隔的列表形式一起指定:
DIR1:DIR2:DIR3:...
The directories are then searched in order from left to right. A single dot .
can be used to specify the current directory. [7]
这些目录被依次从左到右搜索。单个点 .
可以用来指示当前目录。
For example, the following settings create default include and link paths for packages installed in the current directory .
and the include
and lib
directories under /opt/gdbm-1.8.3
and /net
respectively:
例如,下面的设置把安装软件包的当前目录 .
及在 /optgdbm-1.8.3
和 /net
目录下各自的 include
and lib
目录放到默认的 include 和链接路径中去:
$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib
To specify multiple search path directories on the command line, the options -I
and -L
can be repeated. For example, the following command,
在命令行上可以重复使用 -I
和 -L
选项来指定多个搜索路径的目录。例如,下面的命令,
$ gcc -I. -I/opt/gdbm-1.8.3/include -I/net/include
-L. -L/opt/gdbm-1.8.3/lib -L/net/lib .....
is equivalent to the environment variable settings given above.
等同于上面在环境变量中设置的。
When environment variables and command-line options are used together the compiler searches the directories in the following order:
当环境变量和命令行选项被同时使用时,编译器按下面的次序搜索目录:
- command-line options
-I
and-L
, from left to right (从左到右搜索由命令行-I
和-L
指定的目录) - directories specified by environment variables, such as
C_INCLUDE_PATH
andLIBRARY_PATH
(由环境变量,比如C_INCLUDE_PATH
和LIBRARY_PATH
指定的目录) - default system directories (默认的系统目录)
In day-to-day usage, directories are usually added to the search paths with the options -I
and -L
.
在日常的使用情况中,通常用 -I
和 -L
选项把目录添加到搜索路径。
colon [ˈkəʊlən; ˈkəʊlɒn]:n. 结肠,冒号
[7] 当前目录也可以用一个空的路径元素来指定。比如 :DIR1:DIR2
等同于 .:DIR1:DIR2
。
3.2 Shared libraries and static libraries (共享库和静态库)
Although the example program above has been successfully compiled and linked, a final step is needed before being able to load and run the executable file.
虽然上面的例子程序被成功编译和链接,但生成的可执行文件要能被载入并运行,还缺少最后一步。
If an attempt is made to start the executable directly, the following error will occur on most systems:
如果你试图直接启动该可执行文件,在绝大部分系统上将报下面的错:
$ ./a.out
./a.out: error while loading shared libraries:
libgdbm.so.3: cannot open shared object file:
No such file or directory
This is because the GDBM package provides a shared library
. This type of library requires special treatment – it must be loaded from disk before the executable will run.
这是由于 GDBM 软件包提供的共享库的缘故。这种类型的库需要特殊对待 – 在可执行文件运行以前,它必须先从磁盘上被载入。
External libraries are usually provided in two forms: static libraries
and shared libraries
. Static libraries are the .a
files seen earlier. When a program is linked against a static library, the machine code from the object files for any external functions used by the program is copied from the library into the final executable.
外部库通常用两种形式提供:静态库和共享库。静态库就是前面看到过的 .a
文件。当程序与一个静态库链接时,该程序用到的外部函数 (在用到的静态库包含的对象文件中) 的机器码被从库中复制到最终生成的可执行文件中。
Shared libraries are handled with a more advanced form of linking, which makes the executable file smaller. They use the extension .so
, which stands for shared object
.
处理共享库用的是一种更加高级的链接形式,它会使得可执行文件比较小。共享库使用 .so
后缀名,它代表共享对象 (shared object)。
An executable file linked against a shared library contains only a small table of the functions it requires, instead of the complete machine code from the object files for the external functions. Before the executable file starts running, the machine code for the external functions is copied into memory from the shared library file on disk by the operating system – a process referred to as dynamic linking
.
一个与共享库链接的可执行文件仅仅包含它用到的函数相关的一个表格,而不是外部函数所在的对象文件的整个机器码。在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中 – 这个过程被称作动态链接 (dynamic linking)。
Dynamic linking makes executable files smaller and saves disk space, because one copy of a library can be shared between multiple programs. Most operating systems also provide a virtual memory mechanism which allows one copy of a shared library in physical memory to be used by all running programs, saving memory as well as disk space.
因为一份库可以在多个程序间共享,所以动态链接使得可执行文件更小,也节省了磁盘空间。绝大部分操作系统提供了虚拟内存机制,该机制允许物理内存中的一份共享库被要用到该库的所有运行的程序共用,节省了内存和磁盘空间。
Furthermore, shared libraries make it possible to update a library without recompiling the programs which use it (provided the interface to the library does not change).
此外,共享库使得升级库而无需重新编译用到它的程序 (只要库提供的接口不变就行)。
Because of these advantages gcc
compiles programs to use shared libraries by default on most systems, if they are available. Whenever a static library libNAME.a
would be used for linking with the option -lNAME
the compiler first checks for an alternative shared library with the same name and a .so
extension.
由于这些优点,如果可能,在绝大部分系统上 gcc
编译程序时默认链接到共享库。使用选项 -lNAME
的情况下,静态库 libNAME
可以用于链接,但编译器首先会检查具有相同名字的 .so
为扩展名的共享库。
In this case, when the compiler searches for the libgdbm
library in the link path, it finds the following two files in the directory /opt/gdbm-1.8.3/lib
:
在上面的例子中,当编译器在链接路径中搜索 libgdbm
时,它在 /opt/gdbm-1.8.3/lib
目录中找到下面两个文件:
$ cd /opt/gdbm-1.8.3/lib
$ ls libgdbm.*
libgdbm.a libgdbm.so
Consequently, the libgdbm.so
shared object file is used in preference to the libgdbm.a
static library.
结果是 libgdbm.so
共享库优先于 libgdbm.a
静态库被使用。
However, when the executable file is started its loader function must find the shared library in order to load it into memory. By default the loader searches for shared libraries only in a predefined set of system directories, such as /usr/local/lib
and /usr/lib
. If the library is not located in one of these directories it must be added to the load path. [8]
然而,当启动可执行文件时,载入器为了把共享库载入内存,必须先找到它。默认情况下,载入器仅在一些预定义的系统目录中查找共享库,比如 /usr/local/lib
和 /usr/lib
。如果库不在这些目录中,那它必须被添加到载入路径 (load path) 中去。
[8] 注意,原则上包含有要用到的共享库的目录可以通过链接选项 -rpath
存储到可执行文件中去,但通常都不这样做。因为如果库被移走或该可执行文件被复制到另外的系统上,这会产生新的问题。
The simplest way to set the load path is through the environment variable LD_LIBRARY_PATH
. For example, the following commands set the load path to /opt/gdbm-1.8.3/lib
so that libgdbm.so
can be found:
设置载入路径的最简单方法是通过环境变量 LD_LIBRARY_PATH
。例如,下面的命令设置载入路径为 /opt/gdbm-1.8.3/lib
,以便载入器能够找到 libgdbm.so
:
$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib
$ export LD_LIBRARY_PATH
$ ./a.out
Storing key-value pair... done.
The executable now runs successfully, prints its message and creates a DBM file called test
containing the key-value pair testkey
and testvalue
.
现在可执行文件成功运行,打印出消息并创建了一个被称为 test
的 DBM 文件,包含 testkey
和 testvalue
这对键-值对。
To save typing, the LD_LIBRARY_PATH
environment variable can be set once for each session in the appropriate login file, such as .bash_profile
for the GNU Bash shell.
为了不要每次都输入,LD_LIBRARY_PATH
环境变量可以一次性的被设置到 shell 的相应登录文件中,像 GNU Bash shell 的 .bash_profile
文件。
Several shared library directories can be placed in the load path, as a colon separated list DIR1:DIR2:DIR3:...:DIRN
. For example, the following command sets the load path to use the lib
directories under /opt/gdbm-1.8.3
and /opt/gtk-1.4
:
多个共享库目录可以用冒号分隔列表 DIR1:DIR2:DIR3:...:DIRN
的形式放入载入路径中。例如下面的命令设置载入路径,用到了 /opt/gdbm-1.8.3
和 /opt/gtk-1.4
中的 lib
目录:
$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib:/opt/gtk-1.4/lib
$ export LD_LIBRARY_PATH
If the load path contains existing entries, it can be extended using the syntax LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH
. For example, the following command adds the directory /opt/gsl-1.5/lib
to the load path shown above:
如果载入路径包含已有项,可以用语法 LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH
来扩展。例如,下面的命令像上面显示的那样把目录 /opt/gsl-1.5/lib
添加到载入路径中:
$ LD_LIBRARY_PATH=/opt/gsl-1.5/lib:$LD_LIBRARY_PATH
$ echo $LD_LIBRARY_PATH
/opt/gsl-1.5/lib:/opt/gdbm-1.8.3/lib:/opt/gtk-1.4/lib
It is possible for the system administrator to set the LD_LIBRARY_PATH
variable for all users, by adding it to a default login script, such as /etc/profile
. On GNU systems, a system-wide path can also be defined in the loader configuration file /etc/ld.so.conf
.
系统管理员可以为所有用户设置 LD_LIBRARY_PATH
变量,只要把它添加到默认的登录脚本中,比如像 /etc/profile
。在 GNU 系统上,系统范围的路径也可以被定义在载入器配置文件 /etc/ld.so.conf
中。
Alternatively, static linking can be forced with the -static
option to gcc
to avoid the use of shared libraries:
相比较,使用 -static
选项可以迫使 gcc
静态链接,避免使用共享库:
$ gcc -Wall -static -I/opt/gdbm-1.8.3/include/
-L/opt/gdbm-1.8.3/lib/ dbmain.c -lgdbm
This creates an executable linked with the static library libgdbm.a
which can be run without setting the environment variable LD_LIBRARY_PATH
or putting shared libraries in the default directories:
这就创建了一个与静态库 libgdbm.a
链接的可执行文件,它不需要设置环境变量 LD_LIBRARY_PATH
或把共享库存放在默认目录中就可以运行:
$ ./a.out
Storing key-value pair... done.
As noted earlier, it is also possible to link directly with individual library files by specifying the full path to the library on the command line. For example, the following command will link directly with the static library libgdbm.a
,
正像前面一样要注意的,通过在命令行上指定库的完整路径,直接与个别库文件链接也是可以的。例如,下面的命令将直接与静态库 libgdbm.a
链接,
$ gcc -Wall -I/opt/gdbm-1.8.3/include
dbmain.c /opt/gdbm-1.8.3/lib/libgdbm.a
and the command below will link with the shared library file libgdbm.so
:
而下面的命令将与共享库文件 libgdbm.so
链接:
$ gcc -Wall -I/opt/gdbm-1.8.3/include
dbmain.c /opt/gdbm-1.8.3/lib/libgdbm.so
In the latter case it is still necessary to set the library load path when running the executable.
对于后者,要运行该可执行文件,还是需要设置该库的载入路径。
$ gcc -Wall -I/opt/gdbm-1.8.3/include
dbmain.c /opt/gdbm-1.8.3/lib/libgdbm.a
3.3 C language standards (C 语言标准)
By default, gcc
compiles programs using the GNU dialect of the C language, referred to as GNU C
. This dialect incorporates the official ANSI/ISO standard for the C language with several useful GNU extensions, such as nested functions and variable-size arrays. Most ANSI/ISO programs will compile under GNU C without changes.
默认情况下,gcc
编译程序用的是 C 语言的 GNU 方言 (一种 C 语言的 GNU 实现),被称为 GNU C。该实现集成了 C 语言官方 ANSI/ISO 标准和一些有用的 GNU 对 C 语言的扩展,比如内嵌函数和变长数组 [9]。绝大部分符合 ANSI/ISO 的程序无需修改就能在 GNU C 下编译。
There are several options which control the dialect of C used by gcc
. The most commonly-used options are -ansi
and -pedantic
. The specific dialects of the C language for each standard can also be selected with the -std
option.
有几个选项可以控制 gcc
使用的 C 语言。最常用的选项是 -ansi
and -pedantic
。每种标准的 C 语言特定方言也可以使用 -std
选项来选择。
[9] 这两者在标准中都是非法的。
pedantic [pɪˈdæntɪk]:adj. 迂腐的,学究式的,卖弄学问的,假装学者的
3.3.1 ANSI/ISO
Occasionally a valid ANSI/ISO program may be incompatible with the extensions in GNU C. To deal with this situation, the compiler option -ansi
disables those GNU extensions which conflict with the ANSI/ISO standard. On systems using the GNU C Library (glibc
) it also disables extensions to the C standard library. This allows programs written for ANSI/ISO C to be compiled without any unwanted effects from GNU extensions.
有时候,一个合法的 ANSI/ISO 程序可能并不兼容于 GNU C 中的扩展特性。为了处理这种情况,编译器选项 -ansi
禁止那些与 ANSI/ISO 标准冲突的 GNU 扩展特性。在使用 GNU C 库 (glibc) 的系统上,该选项也禁止了对 C 标准库的扩展。这样就允许那些基于 ANSI/ISO C 编写的程序在没有任何来自 GNU 扩展的情况下编译。
occasionally [əˈkeɪʒnəli]:adv. 偶尔,间或
For example, here is a valid ANSI/ISO C program which uses a variable called asm
:
例如,下面是一个合法的 ANSI/ISO C 程序,它用到一个名为 asm
的变量:
#include <stdio.h>
int
main (void)
{
const char asm[] = "6502";
printf ("the string asm is '%s'\n", asm);
return 0;
}
The variable name asm
is valid under the ANSI/ISO standard, but this program will not compile in GNU C because asm
is a GNU C keyword extension (it allows native assembly instructions to be used in C functions). Consequently, it cannot be used as a variable name without giving a compilation error:
变量名 asm
在 ANSI/ISO 标准中是合法的,但 asm
是 GNU 扩展的关键字 (它允许 C 函数中使用本地汇编指令),所以该程序在 GNU C 下不能编译。因此,它不能用作变量名,会产生编译错误:
$ gcc -Wall ansi.c
ansi.c: In function `main':
ansi.c:6: parse error before `asm'
ansi.c:7: parse error before `asm'
consequently [ˈkɒnsɪkwəntli]:adv. 因此,结果,所以
In contrast, using the -ansi
option disables the asm
keyword extension, and allows the program above to be compiled correctly:
相对应的,使用 -ansi
选项禁止 asm
这个扩展关键字后,上面的程序就能成功编译:
$ gcc -Wall -ansi ansi.c
$ ./a.out
the string asm is '6502'
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 4
-rw-rw-r-- 1 strong strong 125 Sep 28 15:16 ansi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ cat ansi.c
#include <stdio.h>
int main (void)
{
const char asm[] = "6502";
printf ("the string asm is '%s'\n", asm);
return 0;
}
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall ansi.c
ansi.c: In function ‘main’:
ansi.c:5:14: error: expected identifier or ‘(’ before ‘asm’
const char asm[] = "6502";
^
ansi.c:6:39: error: expected expression before ‘asm’
printf ("the string asm is '%s'\n", asm);
^
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall -ansi ansi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 16
-rw-rw-r-- 1 strong strong 125 Sep 28 15:16 ansi.c
-rwxrwxr-x 1 strong strong 8664 Sep 28 15:17 a.out
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ./a.out
the string asm is '6502'
strong@foreverstrong:~/Desktop/makefile_work$
For reference, the non-standard keywords and macros defined by the GNU C extensions are asm
, inline
, typeof
, unix
and vax
. More details can be found in the GCC Reference Manual Using GCC
(see section Further reading).
为了便于参考,列出 GNU C 扩展特性定义的非标准关键字和宏 asm
, inline
, typeof
, unix
and vax
。更多细节可以在 GCC 参考手册 Using GCC
中找到 (see section Further reading)。
The next example shows the effect of the -ansi
option on systems using the GNU C Library, such as GNU/Linux systems. The program below prints the value of pi, pi=3.14159…, from the preprocessor definition M_PI
in the header file math.h
:
下面的例子展示了 -ansi
选项在使用 GNU C 库的系统 (比如像 GNU/Linux 系统) 上的效果。下面的程序打印 pi 的值,pi=3.14159…,预定义的 M_PI
来自头文件 math.h
:
#include <math.h>
#include <stdio.h>
int
main (void)
{
printf("the value of pi is %f\n", M_PI);
return 0;
}
The constant M_PI
is not part of the ANSI/ISO C standard library (it comes from the BSD version of Unix). In this case, the program will not compile with the -ansi
option:
常数 M_PI
并不是 ANSI/ISO C 标准库的一部分 (它来自于 BSD 版本的 Unix)。在这种情况下,该程序不能用 -ansi
选项来编译:
$ gcc -Wall -ansi pi.c
pi.c: In function `main':
pi.c:7: `M_PI' undeclared (first use in this function)
pi.c:7: (Each undeclared identifier is reported only once
pi.c:7: for each function it appears in.)
The program can be compiled without the -ansi
option. In this case both the language and library extensions are enabled by default:
该程序不使用 -ansi
选项就能编译。在这种情况下,对语言和库的扩展两者都被默认打开了:
$ gcc -Wall pi.c
$ ./a.out
the value of pi is 3.141593
It is also possible to compile the program using ANSI/ISO C, by enabling only the extensions in the GNU C Library itself. This can be achieved by defining special macros, such as _GNU_SOURCE
, which enable extensions in the GNU C Library: [9]
编译程序时,只使用 ANSI/ISO C 标准,并且又用到 GNU C 库中的扩展特性是可以的。通过定义几个特殊的宏就可以做到,比如定义 _GNU_SOURCE
,它打开了对 GNU C 库中的扩展的支持:
$ gcc -Wall -ansi -D_GNU_SOURCE pi.c
$ ./a.out
the value of pi is 3.141593
[9] 用来定义宏的 -D
选项将在下一章详细介绍。
The GNU C Library provides a number of these macros (referred to as feature test macros
) which allow control over the support for POSIX extensions (_POSIX_C_SOURCE
), BSD extensions (_BSD_SOURCE
), SVID extensions (_SVID_SOURCE
), XOPEN extensions (_XOPEN_SOURCE
) and GNU extensions (_GNU_SOURCE
).
GNU C 库提供了一些这样的宏,用来控制对不同特性的支持 (参考特征测试宏),POSIX extensions (_POSIX_C_SOURCE
), BSD extensions (_BSD_SOURCE
), SVID extensions (_SVID_SOURCE
), XOPEN extensions (_XOPEN_SOURCE
) and GNU extensions (_GNU_SOURCE
).
The _GNU_SOURCE
macro enables all the extensions together, with the POSIX extensions taking precedence over the others in cases where they conflict. Further information about feature test macros can be found in the GNU C Library Reference Manual
, see section Further reading.
_GNU_SOURCE
宏打开所有的扩展,而 POSIX 扩展在这里如果与其他扩展有冲突,则优先于其他扩展。有关特征测试宏进一步信息可以参见 GNU C 库参考手册,see section Further reading。
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 4
-rw-rw-r-- 1 strong strong 114 Sep 28 15:19 pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ cat pi.c
#include <math.h>
#include <stdio.h>
int main (void)
{
printf("the value of pi is %f\n", M_PI);
return 0;
}
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall -ansi pi.c
pi.c: In function ‘main’:
pi.c:6:37: error: ‘M_PI’ undeclared (first use in this function)
printf("the value of pi is %f\n", M_PI);
^
pi.c:6:37: note: each undeclared identifier is reported only once for each function it appears in
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 16
-rwxrwxr-x 1 strong strong 8600 Sep 28 15:20 a.out
-rw-rw-r-- 1 strong strong 114 Sep 28 15:19 pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ./a.out
the value of pi is 3.141593
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ rm a.out
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 4
-rw-rw-r-- 1 strong strong 114 Sep 28 15:19 pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall -ansi -D_GNU_SOURCE pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 16
-rwxrwxr-x 1 strong strong 8600 Sep 28 15:22 a.out
-rw-rw-r-- 1 strong strong 114 Sep 28 15:19 pi.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ./a.out
the value of pi is 3.141593
strong@foreverstrong:~/Desktop/makefile_work$
3.3.2 Strict ANSI/ISO (严格的 ANSI/ISO 标准)
The command-line option -pedantic
in combination with -ansi
will cause gcc
to reject all GNU C extensions, not just those that are incompatible with the ANSI/ISO standard. This helps you to write portable programs which follow the ANSI/ISO standard.
同时使用命令行选项 -pedantic
和 -ansi
会导致 gcc
拒绝所有的 GNU C 扩展,而不单单是那些不兼容于 ANSI/ISO 标准的。这有助于你写出遵循 ANSI/ISO 标准的可移植的程序。
Here is a program which uses variable-size arrays, a GNU C extension. The array x[n]
is declared with a length specified by the integer variable n
.
下面是一个用到变长数组 (一种 GNU C 扩展) 的程序。数组 x[n]
被声明成具有整数变量 n
指定的长度。
int
main (int argc, char *argv[])
{
int i, n = argc;
double x[n];
for (i = 0; i < n; i++)
x[i] = i;
return 0;
}
This program will compile with -ansi
, because support for variable length arrays does not interfere with the compilation of valid ANSI/ISO programs – it is a backwards-compatible extension:
由于支持变长数组并不会妨碍合法的 ANSI/ISO 程序的编译 (这是一种向后兼容的扩展),该程序可以用 -ansi
编译:
$ gcc -Wall -ansi gnuarray.c
However, compiling with -ansi -pedantic
reports warnings about violations of the ANSI/ISO standard:
但是,如果用 -ansi -pedantic
来编译,就会报有关违反了 ANSI/ISO 标准的警告:
$ gcc -Wall -ansi -pedantic gnuarray.c
gnuarray.c: In function `main':
gnuarray.c:5: warning: ISO C90 forbids variable-size
array `x'
Note that an absence of warnings from -ansi -pedantic does not guarantee that a program strictly conforms to the ANSI/ISO standard. The standard itself specifies only a limited set of circumstances that should generate diagnostics, and these are what -ansi -pedantic
reports.
注意,即使用 -ansi -pedantic
编译没有任何警告,也不能保证程序是严格遵循 ANSI/ISO 标准的。标准本身仅仅指定一套有限的应当产生诊断信息的情形,也就是 -ansi -pedantic
报的这些信息。
circumstance [ˈsɜ:kəmstəns]:n. 环境,状况,境遇,(尤指) 经济状况,命运 vt. 处于某种情况
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 4
-rw-rw-r-- 1 strong strong 127 Sep 28 16:00 gnuarray.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ cat gnuarray.c
int main (int argc, char *argv[])
{
int i, n = argc;
double x[n];
for (i = 0; i < n; i++)
x[i] = i;
return 0;
}
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall -ansi gnuarray.c
gnuarray.c: In function ‘main’:
gnuarray.c:5:10: warning: variable ‘x’ set but not used [-Wunused-but-set-variable]
double x[n];
^
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 16
-rwxrwxr-x 1 strong strong 8616 Sep 28 16:01 a.out
-rw-rw-r-- 1 strong strong 127 Sep 28 16:00 gnuarray.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ./a.out
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ rm a.out
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ ls -l
total 4
-rw-rw-r-- 1 strong strong 127 Sep 28 16:00 gnuarray.c
strong@foreverstrong:~/Desktop/makefile_work$
strong@foreverstrong:~/Desktop/makefile_work$ gcc -Wall -ansi -pedantic gnuarray.c
gnuarray.c: In function ‘main’:
gnuarray.c:5:3: warning: ISO C90 forbids variable length array ‘x’ [-Wvla]
double x[n];
^
gnuarray.c:5:10: warning: variable ‘x’ set but not used [-Wunused-but-set-variable]
double x[n];
^
strong@foreverstrong:~/Desktop/makefile_work$
3.3.3 Selecting specific standards (选择指定标准)
The specific language standard used by GCC can be controlled with the -std
option. The following C language standards are supported:
可以用 -std
选项来控制 GCC 编译时采用的某个 C 语言标准。有下列 C 语言标准被支持:
-std=c89
or -std=iso9899:1990
The original ANSI/ISO C language standard (ANSI X3.159-1989, ISO/IEC 9899:1990). GCC incorporates the corrections in the two ISO Technical Corrigenda to the original standard.
原来的 ANSI/ISO 语言标准 (ANSI X3.159-1989,ISO/IEC 9899:1990)。GCC 把两份 ISO 技术勘误表中的修正集成到这两份标准中。
-std=iso9899:199409
The ISO C language standard with ISO Amendment 1, published in 1994. This amendment was mainly concerned with internationalization, such as adding support for multibyte characters to the C library.
1994 年发布的 ISO C 语言标准的第一次修正版。该修正版主要涉及到国际化方面,比如为 C 库添加了多字节字符的支持。
-std=c99
or -std=iso9899:1999
The revised ISO C language standard, published in 1999 (ISO/IEC 9899:1999).
1999 年发布的修正过的 ISO C 语言标准 (ISO/IEC 9899:1999)。
The C language standards with GNU extensions can be selected with the options -std=gnu89
and -std=gnu99
.
附带 GNU 扩展的 C 语言标准可以用选项 -std=gnu89
和 -std=gnu99
来选择。
3.4 Warning options in -Wall
(-Wall
中的警告选项)
As described earlier (see section 2.1 Compiling a simple C program), the warning option -Wall
enables warnings for many common errors, and should always be used. It combines a large number of other, more specific, warning options which can also be selected individually. Here is a summary of these options:
像前面介绍的 (see section 2.1 Compiling a simple C program),警告选项 -Wall
打开了针对许多常见错误的警告,所以最好编译时总使用该选项。它集成了很多的可以被单独指定的警告选项。下面是这些选项的概要:
individually [ˌɪndɪˈvɪdʒuəli]:adv. 个别地,单独地
-Wcomment
(included in -Wall
)
This option warns about nested comments. Nested comments typically arise when a section of code containing comments is later commented out
:
该选项对嵌套的注释发出警告。当包含注释的某段代码其后又被注释掉时就会产生嵌套的注释:
/* commented out
double x = 1.23 ; /* x-position */
*/
Nested comments can be a source of confusion – the safe way to comment out
a section of code containing comments is to surround it with the preprocessor directive #if 0 ... #endif
:
嵌套注释可能引起混乱 – 注释掉一段本身就包含注释的代码的安全方法是用预处理指示符 #if 0 ... #endif
:
/* commented out */
#if 0
double x = 1.23 ; /* x-position */
#endif
-Wformat
(included in -Wall
)
This option warns about the incorrect use of format strings in functions such as printf
and scanf
, where the format specifier does not agree with the type of the corresponding function argument.
该选项警告像 printf
和 scanf
这种函数中格式化字符串的误用,即格式化字符串与对应的函数参数的类型不一致。
-Wunused
(included in -Wall
)
This option warns about unused variables. When a variable is declared but not used this can be the result of another variable being accidentally substituted in its place. If the variable is genuinely not needed it can be removed from the source code.
该选项警告有没使用到的变量。当一个变量被声明但没有被使用时,可能是另一个变量意外地取代了它的位置。如果该变量确实不需要,那就从源代码中删除它。
-Wimplicit
(included in -Wall
)
This option warns about any functions that are used without being declared. The most common reason for a function to be used without being declared is forgetting to include a header file.
该选项对任何没有声明就被使用的函数发出警告。没有声明就被使用函数的最常见原因是忘了包含该函数所在的头文件。
-Wreturn-type
(included in -Wall
)
This option warns about functions that are defined without a return type but not declared void. It also catches empty return statements in functions that are not declared void. For example, the following program does not use an explicit return value:
该函数警告被定义的函数没有返回类型但并没有声明返回 void。它也能捕捉到返回值不是 void,但函数中返回空的 return 语句。例如,下面的程序没有显式的返回值:
#include <stdio.h>
int
main (void)
{
printf ("hello world\n");
return;
}
The lack of a return value in the code above could be the result of an accidental omission by the programmer – the value returned by the main function is actually the return value of the printf
function (the number of characters printed). To avoid ambiguity, it is preferable to use an explicit value in the return statement, either as a variable or a constant, such as return 0
.
上面代码中缺少返回值可能是程序员意外省略的结果 – main 函数返回的值实际上是 printf
函数的返回值 (即打印出的字符数)。为了避免暧昧不清,最好在 return 语句中返回显式的值,即或者是某个变量,或者是某个常数,比如像 return 0。
The complete set of warning options included in -Wall
can be found in the GCC Reference Manual Using GCC
(see section Further reading). The options included in -Wall
have the common characteristic that they report constructions which are always wrong, or can easily be rewritten in an unambiguously correct way. This is why they are so useful – any warning produced by -Wall
can be taken as an indication of a potentially serious problem.
-Wall
中包括有哪些警告选项在 GCC参考手册 Using GCC
中都能找到 (see section Further reading)。-Wall
中包含的选项有个普遍的特性,它们报告总是有问题的代码构造,或是很容易用明白无误的方法改写的错。这就是为什么它们如此有用 – -Wall
产生的任何警告可以被看作是有潜在严重问题的指示。
omission [əˈmɪʃn]:n. 疏忽,遗漏,省略,冗长
accidental [ˌæksɪˈdentl]:adj. 意外的,偶然的,附属的,临时记号的 n. 次要方面,非主要的特性,临时记号
unambiguously [ˌʌnæmˈbɪɡjuəsli]:adv. 不含糊地,明白地,单意义地
indication [ˌɪndɪˈkeɪʃn]:n. 指示,指出,迹象,象征
3.5 Additional warning options (其他警告选项)
GCC provides many other warning options that are not included in -Wall
, but are often useful. Typically these produce warnings for source code which may be technically valid but is very likely to cause problems. The criteria for these options are based on experience of common errors – they are not included in -Wall
because they only indicate possibly problematic or suspicious
code.
GCC 还提供了许多其他警告选项,他们并没有包括在 -Wall
之内,但也很有用。典型的,这些选项对那些从技术上讲合法,但可能导致问题的代码产生警告。GCC 提供这些选项是基于程序员所犯常见错误的经验 – 它们没有被包括在 -Wall
是因为它们仅意味着可能有错误或是代码比较可疑。
suspicious [səˈspɪʃəs]:adj. 可疑的,怀疑的,多疑的
Since these warnings can be issued for valid code it is not necessary to compile with them all the time. It is more appropriate to use them periodically and review the results, checking for anything unexpected, or to enable them for some programs or files.
由于对合法代码也可能报警,所以在编译时并不是总用到这些选项。周期性地使用这些选项并查看输出的结果,检查任何意外的输出,或仅在某些程序和文件中打开它们,可能更合适一点。
-W
This is a general option similar to -Wall
which warns about a selection of common programming errors, such as functions which can return without a value (also known as falling off the end of the function body
), and comparisons between signed and unsigned values. For example, the following function tests whether an unsigned integer is negative (which is impossible, of course):
这是一个类似 -Wall
的通用选项,它对一些常见编程错误产生警告,比如像需要返回值但又没有返回值的函数 (also known as falling off the end of the function body
),以及对有符号数与无符号数进行比较。例如,下面的函数测试一个无符号数是否是负数 (当然这是不可能的):
int
foo (unsigned int x)
{
if (x < 0)
return 0; /* cannot occur */
else
return 1;
}
Compiling this function with -Wall
does not produce a warning,
用 -Wall
来编译该函数不会输出警告信息,
$ gcc -Wall -c w.c
but does give a warning with -W
:
但用 -W
编译时,报警了:
$ gcc -W -c w.c
w.c: In function `foo':
w.c:4: warning: comparison of unsigned
expression < 0 is always false
In practice, the options -W
and -Wall
are normally used together.
实际上,-W
和 -Wall
选项通常同时使用。
-Wconversion
This option warns about implicit type conversions that could cause unexpected results. For example, the assignment of a negative value to an unsigned variable, as in the following code,
该选项警告可能引起意外结果的隐式类型转换。例如,像下面代码中的把一个负数赋值给一个无符号变量,
unsigned int x = -1;
is technically allowed by the ANSI/ISO C standard (with the negative integer being converted to a positive integer, according to the machine representation) but could be a simple programming error. If you need to perform such a conversion you can use an explicit cast, such as ((unsigned int) -1)
, to avoid any warnings from this option. On two’s-complement machines the result of the cast gives the maximum number that can be represented by an unsigned integer.
在技术上,ANSI/ISO C 标准是允许这样做的 (负整数被转换成一个正整数,因机器而不同),但这也可能是一个简单的编程错误。如果你需要实施这样一种转换,你可以用显式转换,比如像 ((unsigned int) -1)
,以避免来自该选项的警告。在 2 的补码的机器上,上面转换的结果是赋给一个无符号整数所能表示的最大值。
-Wshadow
This option warns about the redeclaration of a variable name in a scope where it has already been declared. This is referred to as variable shadowing
, and causes confusion about which occurrence of the variable corresponds to which value. The following function declares a local variable y
that shadows the declaration in the body of the function:
该选项用来警告这样一种情况,在定义过某个变量的代码范围内再次定义一个同名的变量。这被称作变量遮蔽,导致在变量出现的地方搞不清其对应哪个值。下面的函数声明的一个局部变量 y
,它遮蔽了该函数体内的另一个变量 y
的声明:
double
test (double x)
{
double y = 1.0;
{
double y;
y = x;
}
return y;
}
This is valid ANSI/ISO C, where the return value is 1. The shadowing of the variable y
might make it seem (incorrectly) that the return value is x
, when looking at the line y = x
(especially in a large and complicated function). Shadowing can also occur for function names. For example, the following program attempts to define a variable sin
which shadows the standard function sin(x)
.
这是合法的 ANSI/ISO C 程序,它的返回值是 1。当看到 y = x
这一行时 (尤其在大的复杂的函数中),对变量 y 的遮蔽可能使得它看上去返回值是 x (不正确)。函数名也可能被遮蔽。例如,下面的程序试图定义一个会遮蔽标准函数 sin(x)
的变量 sin
。
double
sin_series (double x)
{
/* series expansion for small x */
double sin = x * (1.0 - x * x / 6.0);
return sin;
}
This error will be detected by the -Wshadow
option.
-Wshadow
选项可以检测出这个错。
-Wcast-qual
This option warns about pointers that are cast to remove a type qualifier, such as const
. For example, the following function discards the const
qualifier from its input argument, allowing it to be overwritten:
该选项警告对指针的转换操作移除了某种类型修饰符,比如像 const。例如,下面的函数丢弃了来自输入参数的 const
修饰符,从而允许覆盖指针所指向的空间:
void
f (const char * str)
{
char * s = (char *)str;
s[0] = '\0';
}
The modification of the original contents of str
is a violation of its const
property. This option will warn about the improper cast of the variable str
which allows the string to be modified.
对 str
指向的原始内容的改写是违反它的 const
性质的。该选项将警告允许对 str
变量所指向的字符串做修改的不合适的类型转换。
-Wwrite-strings
This option implicitly gives all string constants defined in the program a const
qualifier, causing a compile-time warning if there is an attempt to overwrite them. The result of modifying a string constant is not defined by the ANSI/ISO standard, and the use of writable string constants is deprecated in GCC.
该选项隐含的使得定义在程序中的所以字符串常量都带有 const
修饰符,导致如果有代码试图覆写这些字符串,就会在编译时报警。修改一个字符串常量会导致什么结果,ANSI/ISO 标准并没有说明。在 GCC 中是使用可写的字符串常量是会报警的 (编译器会抱怨,以后甚至会禁止这样做)。
deprecate [ˈdeprəkeɪt]:vt. 反对,抨击,轻视,声明不赞成
-Wtraditional
This option warns about parts of the code which would be interpreted differently by an ANSI/ISO compiler and a traditional
pre-ANSI compiler. [10] When maintaining legacy software it may be necessary to investigate whether the traditional or ANSI/ISO interpretation was intended in the original code for warnings generated by this option.
该选项对那些在 ANSI/ISO 编译器下和在 ANSI 之前的传统编译器下编译方式不同的代码进行警告。当维护老的原有的软件时,对于该选项产生的警告,可能需要调查原始代码是接受传统编译呢还是接受 ANSI/ISO 标准编译。
The options above produce diagnostic warning messages, but allow the compilation to continue and produce an object file or executable. For large programs it can be desirable to catch all the warnings by stopping the compilation whenever a warning is generated. The -Werror
option changes the default behavior by converting warnings into errors, stopping the compilation whenever a warning occurs.
上面的选项会生成诊断性的警告信息,但允许编译过程继续并生成对象文件或可执行文件。对于大型程序,可能只要有警告信息产生,就停止编译。以便捕捉所有警告。 -Werror
选项通过把警告转变成错误,改变了编译器的默认行为,即只要有警告产生就停止编译。
References
http://lampwww.epfl.ch/~fsalvi/docs/gcc/www.network-theory.co.uk/docs/gccintro/index.html
https://www.linuxtopia.org/online_books/an_introduction_to_gcc/index.html
https://github.com/l10n-tw/An-Introduction-to-GCC-zh_TW