GCC警告选项例解
gcc 常见的编译警告与错误(按字母顺序排列)
gcc 常见的编译警告与错误(按字母顺序排列)C语言初学者遇到的最大问题往往是看不懂编译错误,进而不知如何修改程序。
有鉴于此,本附录罗列了用gcc编译程序时经常出现的编译警告与错误。
需要提醒读者的是,出现警告(warning)并不影响目标程序的生成,但出现错误(error)则无法生成目标程序。
为便于读者查阅,下面列出了经常遇到的警告与错误,给出了中英文对照(英文按字典顺序排列),并对部分错误与警告做了必要的解释。
#%s expects \FILENAME\ or …#%s 需要\FILENAME\ 或…#%s is a deprecated GCC extension#%s 是一个已过时的GCC 扩展#%s is a GCC extension#%s 是一个GCC 扩展#~ error:#~ 错误:#~ In file included from %s:%u#~ 在包含自%s:%u 的文件中#~ internal error:#~ 内部错误:#~ no newline at end of file#~ 文件未以空白行结束#~ warning:#~ 警告:#elif after #else#elif 出现在#else 后#elif without #if#elif 没有匹配的#if#else after #else#else 出现在#else 后#else without #if#else 没有匹配的#if#endif without #if#endif 没有匹配的#if#include nested too deeply#include 嵌套过深#include_next in primary source file#include_next 出现在主源文件中#pragma %s %s is already registered#pragma %s %s 已经被注册#pragma %s is already registered#pragma %s 已经被注册#pragma once in main file#pragma once 出现在主文件中#pragma system_header ignored outside include file#pragma system_heade 在包含文件外被忽略%.*s is not a valid universal character%.*s 不是一个有效的Unicode 字符%s in preprocessing directive预处理指示中出现%s%s is a block device%s 是一个块设备%s is shorter than expected%s 短于预期%s is too large%s 过大%s with no expression%s 后没有表达式%s: not used because `%.*s’ defined as `%s’ not `%.*s’%s:未使用因为‘%.*s’被定义为‘%s’而非‘%*.s’%s: not used because `%.*s’ is poisoned%s:未使用因为‘%.*s’已被投毒%s: not used because `%.*s’ not def ined%s:未使用因为‘%.*s’未定义%s: not used because `%s’ is defined%s:未使用因为‘%s’已定义%s: not used because `__COUNTER__’ is invalid%s:未使用因为‘__COUNTER__’无效(\%s\ is an alternative token for \%s\ in C++)(在C++ 中“%s”会是“%s”的替代标识符)(this will be reported only once per input file)(此警告为每个输入文件只报告一次)\%s\ after # is not a positive integer# 后的“%s”不是一个正整数\%s\ after #line is not a positive integer#line 后的“%s”不是一个正整数\%s\ cannot be used as a macro name as it is an operator in C++ “%s”不能被用作宏名,因为它是C++ 中的一个操作符\%s\ is not a valid filename“%s”不是一个有效的文件名\%s\ is not defined“%s”未定义\%s\ may not appear in macro parameter list“%s不能出现在宏参数列表中\%s\ re-asserted重断言“%s”\%s\ redefined“%s重定义\/*\ within comment“/*出现在注释中\\x used with no following hex digits\\x 后没有16 进制数字\defined\ cannot be used as a macro name“defined不能被用作宏名__COUNTER__ expanded inside directive with -fdirectives-only带-fdirectives-only 时__COUNTER__ 在指示中扩展__V A_ARGS__ can only appear in the expansion of a C99 variadic macro __V A_ARGS__ 只能出现在C99 可变参数宏的展开中_Pragma takes a parenthesized string literal_Pragma 需要一个括起的字符串字面常量‘%.*s’ is not in NFC‘%.*s’不在NFC 中‘%.*s’ is not in NFKC‘%.*s’不在NFKC 中‘##’ cannot appear at either end of a macro expansion‘##’不能出现在宏展开的两端‘#’ is not followed by a macro parameter‘#’后没有宏参数‘$’ in identifier or number‘$’出现在标识符或数字中‘:’ without preceding ‘?’‘:’前没有‘?’‘?’ without following ‘:’‘?’后没有‘:’'return' with a value, in function returning void在void返回类型的函数中,return返回值。
gcc的使用简介与命令行参数说明
gcc的使⽤简介与命令⾏参数说明(⼀) gcc的基本⽤法(⼆) 警告提⽰功能选项(三) 库操作选项(四) 调试选项(五) 交叉编译选项(⼀) gcc的基本⽤法使⽤gcc编译器时,必须给出⼀系列必要的调⽤参数和⽂件名称。
不同参数的先后顺序对执⾏结果没有影响,只有在使⽤同类参数时的先后顺序才需要考虑。
如果使⽤了多个 -L 的参数来定义库⽬录,gcc会根据多个 -L 参数的先后顺序来执⾏相应的库⽬录。
因为很多gcc参数都由多个字母组成,所以gcc参数不⽀持单字母的组合,Linux中常被叫短参数(short options),如 -dr 与 -d -r 的含义不⼀样。
gcc编译器的调⽤参数⼤约有100多个,其中多数参数我们可能根本就⽤不到,这⾥只介绍其中最基本、最常⽤的参数。
gcc最基本的⽤法是:gcc [options] [filenames]其中,options就是编译器所需要的参数,filenames给出相关的⽂件名称,最常⽤的有以下参数:-c只编译,不链接成为可执⾏⽂件。
编译器只是由输⼊的 .c 等源代码⽂件⽣成 .o 为后缀的⽬标⽂件,通常⽤于编译不包含主程序的⼦程序⽂件。
-o output_filename确定输出⽂件的名称为output_filename。
同时这个名称不能和源⽂件同名。
如果不给出这个选项,gcc就给出默认的可执⾏⽂件 a.out 。
-g产⽣符号调试⼯具(GNU的 gdb)所必要的符号信息。
想要对源代码进⾏调试,就必须加⼊这个选项。
-O对程序进⾏优化编译、链接。
采⽤这个选项,整个源代码会在编译、链接过程中进⾏优化处理,这样产⽣的可执⾏⽂件的执⾏效率可以提⾼,但是编译、链接的速度就相应地要慢⼀些,⽽且对执⾏⽂件的调试会产⽣⼀定的影响,造成⼀些执⾏效果与对应源⽂件代码不⼀致等⼀些令⼈“困惑”的情况。
因此,⼀般在编译输出软件发⾏版时使⽤此选项。
-O2⽐ -O 更好的优化编译、链接。
常见gcc编译警告整理以及解决方法【收藏】
常见gcc编译警告整理以及解决方法【收藏】
1、warning: no newline at end of file
在文件最后一行加上回车键
解释:在《Rationale for the C99 standard》一文中,有C99的相关信息:
A backslash immediately before a newline has long been used to continue string literals, as well as preprocessing command lines. In the interest of easing machine generation of C, and of transporting code to machines with restrictive physical line lengths, the C89 Committee generalized this mechanism to permit any token to be continued by interposing a backslash/newline sequence.
c/c++代码的每一行后面有一个结束符,也就是newline。
避免当被include
的文件展开后,前一个文件的最后一行与后一个文件的第一行直接被连接成一行从而造成错误。
2、warning: comparison between pointer and integer
解释:integer与pointer比较
3、warning: assignment discards qualifiers from pointer target type。
GCC(警告.优化以及调试选项)
GCC(警告.优化以及调试选项)[介绍]gcc and g 分别是gnu的c & c 编译器gcc/g 在执行编译工作的时候,总共需要4步1.预处理,生成.i的文件预处理器cpp2.将预处理后的文件不转换成汇编语言,生成文件.s编译器egcs3.有汇编变为目标代码(机器代码)生成.o的文件汇编器as4.连接目标代码,生成可执行程序连接器ld1.总体选项-E只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.例子用法:gcc -E hello.c > pianoapan.txtgcc -E hello.c | more慢慢看吧,一个hello word 也要与处理成800行的代码-S只激活预处理和编译,就是指把文件编译成为汇编代码。
例子用法gcc -S hello.c他将生成.s的汇编代码,你可以用文本编辑器察看-c只激活预处理,编译,和汇编,也就是他只把程序做成obj文件例子用法:gcc -c hello.c他将生成.o的obj文件2.目录选项-Idir在你是用#include'file'的时候,gcc/g 会先在当前目录查找你所制定的头文件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他回先在你所制定的目录查找,然后再按常规的顺序去找.对于#include,gcc/g 会到-I制定的目录查找,查找不到,然后将到系统的缺省的头文件目录查找-include file-i相当于“#include”包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include例子用法:gcc hello.c -include /root/pianopan.h-I-就是取消前一个参数的功能,所以一般在-Idir之后使用-idirafter dir在-I的目录里面查找失败,讲到这个目录里面查找.-iprefix prefix-iwithprefix dir一般一起使用,当-I的目录查找失败,会到prefix dir下查找-Ldir制定编译的时候,搜索库的路径。
最新GCC编译器选项及优化提示
G C C编译器选项及优化提示GCC编译器选项及优化提示GCC编译器选项及优化提示2010-08-01 19:41很多弟兄可能都很关心如何优化编译自己的程序,虽然本人不赞成"骨灰"玩法,却也不得不承认这是掌握gcc的绝佳途径;因此献上此帖,以供各位玩家参考,绝对原创噢=大多数程序和库在编译时默认的优化级别是"2"(使用gcc选项:"-O2")并且在Intel/AMD平台上默认按照i386处理器来编译。
如果你只想让编译出来的程序运行在特定的平台上,就需要执行更高级的编译器优化选项,以产生只能运行于特定平台的代码。
一种方法是修改每个源码包中的Makefile文件,在其中寻找CFLAGS和CXXFLAGS变量(C和C++编译器的编译选项)并修改它的值。
一些源码包比如binutils,gcc,glibc等等,在每个子文件夹中都有Makefile文件,这样修改起来就太累了!另一种简易做法是设置CFLAGS和CXXFLAGS环境变量。
大多数configure 脚本会使用这两个环境变量代替Makefile文件中的值。
但是少数configure脚本并不这样做,他们必须需要手动编辑才行。
为了设置CFLAGS和CXXFLAGS环境变量,你可以在bash中执行如下命令(也可以写进.bashrc以成为默认值):export CFLAGS="-O3-march="&&CXXFLAGS=$CFLAGS这是一个确保能够在几乎所有平台上都能正常工作的最小设置。
"-march"选项表示为特定的cpu类型编译二进制代码(不能在更低级别的cpu上运行),Intel通常是:pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium-m,prescott,nocona说明:pentium3m/pentium4m是笔记本用的移动P3/P4;pentium-m是迅驰I/II代笔记本的cpu;prescott是带SSE3的P4(以滚烫到可以煎鸡蛋而闻名);nocona则是最新的带有EMT64(64位)的P4(同样可以煎鸡蛋)AMD通常是:k6,k6-2,k6-3,athlon,athlon-tbird,athlon-xp,athlon-mp,opteron,athlon64,athlon-fx用AMD的一般都是DIYer,就不必解释了吧。
3.3 gcc警告提示功能
除了-pedantic之外,gcc还有一些其他编译选项也 除了-pedantic之外,gcc还有一些其他编译选项也 能够产生有用的警告信息。这些选项大多以能够产生有用的警告信息。这些选项大多以-W开 头,其中最有价值的当数-Wall了,使用它能够使 头,其中最有价值的当数-Wall了,使用它能够使 gcc产生尽可能多的警告信息。例如: gcc产生尽可能多的警告信息。例如: [david@DAVID david]$ gcc -Wall bad.c -o bad bad.c:3: warning: return type of 'main' is not 'int' bad.c: In function 'main': bad.c:4: warning: unused variable 'var' bad.c:6:2: warning: no newline at end of file
3.3 gcc警告提示功能 gcc警告提示功能
gcc包含完整的出错检查和警告提示功能, gcc包含完整的出错检查和警告提示功能, 它们可以帮助Linux程序员尽快找到错误代 它们可以帮助Linux程序员尽快找到错误代 码,从而写出更加专业和优美的代码。先 来读读例3 来读读例3-2所示的程序,这段代码写得很 糟糕,仔细检查一下不难挑出如下毛病: main函数的返回值被声明为void,但实 main函数的返回值被声明为void,但实 际上应该是int; 际上应该是int; 使用了GNU语法扩展,即使用long 使用了GNU语法扩展,即使用long long 来声明64位整数,仍不符合ANSI/ISO C语 来声明64位整数,仍不符合ANSI/ISO C语 言标准; main函数在终止前没有调用return语句。 main函数在终止前没有调用return语句。
gcc编译报错解决方案
Gcc最基本的用法是∶gcc [options] [filenames] 其中options就是编译器所需要的参数,filenames给出相关的文件名称。
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。
如果不给出这个选项,gcc就给出预设的可执行文件a.out。
1.linker input file unused because linking not done我在Windows下使用SQLite编了个C++程序,在编写Makefile并使用cygwin 中的g++进行编译链接时遇到如下的错误:linker input file unused because linking not done我的语句是g++ -c a.cpp -lsqlite3到网上查了一下,问题出在链接数据库的语句不应出现在编译语句里面。
上面的语句里面有-c 即编译compile,所以命令会忽略掉所有的-l 链接库的命令。
而要链接数据库,应该在生成可执行文件时才使用。
正确的使用链接的语句应该是g++ a.o -L. -lsqlite3 -o exename2.Linux系统的头文件和库文件搜索路径**#include**的头文件,连结数据库,系统定义,总共有下列来源指定gcc去那找。
∙当初在编译时指定的(在~gcc/gcc/collect2.c:locatelib()∙写在specs内的(针对rpm包)∙后来用-D -I -L指定的∙gcc环境变量设定(编译的时候)∙ld.so的环境变量(这是run time的时候)头文件gcc 在编译时如何去寻找所需要的头文件:∙header file的搜寻会从-I开始∙然后找gcc的环境变量C_INCLUDE_PA TH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PA TH∙再找内定目录:o/usr/includeo/usr/local/includeo/usr/lib/gcc-lib/i386-linux/2.95.2/includeo/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3o/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include∙库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是o/usr/includeo prefix/includeo prefix/xxx-xxx-xxx-gnulibc/includeo prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include库文件cos()等函式库的选项要多加-lm∙编译的时候:gcc会去找-L∙再找gcc的环境变量LIBRARY_PATH∙再找内定目录/lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的运行时动态库的搜索路径1 在配置文件/etc/ld.so.conf中指定动态库搜索路径2 通过环境变量LD_LIBRARY_PA TH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)3 在编译目标代码时指定该程序的动态库搜索路径(还可以在编译目标代码时指定程序的动态库搜索路径。
【GCC】gcc警告选项汇总--编辑中gcc编译选项
【GCC】gcc警告选项汇总--编辑中gcc编译选项⽬录参考原⽂:https:///qq_17308321/article/details/79979514前⾔警告:不是错误的,但是有风险或表明可能有错误。
英⽂原⽂:请求或取消警告选项加上-Wall吧,gcc 默认不加参数的情况下连定义了返回值的函数没有返回值都不报错。
-Wall,-Wextra 就是加-Wall 和-Wall不启动的选项也加上()-fsyntax-only检查代码中的语法错误,但除此之外不要做任何事情。
-w (⼩写)禁⽌所有警告消息。
-W (⼤写)以“ -W ”请求特定的警告 - 可以隐式地请求隐式声明的警告。
-W和-Wall的区别-Wall选项意思是编译后显⽰所有警告。
-W选项类似-Wall,会显⽰警告,但是只显⽰编译器认为会出现错误的警告。
在编译⼀些项⽬的时候可以-W和-Wall选项⼀起使⽤。
gcc -W -Wall test_w_wall testwwall.c-Werror=将指定的警告转换为错误。
请注意,指定-Werror = foo会⾃动隐含-W foo 。
但是, -Wno-error = foo并不意味着什么。
反过来:-Wno-error取消编译选项-Werror⽤途:假设我们使⽤了⼀个⼈的代码A⽬录,⾥⾯有⼀个-Werror的选项,把所有的警告当做错误;⼜使⽤了另⼀个⼈的代码B⽬录,⾥⾯存在⼀堆Warning。
这样,当我们把它们合在⼀起编译的时候,A中的-Werror选项会导致B的代码编译不过。
但我们⼜不想去修改B的代码,怎么办?⽅法是,先add_subdirectory(A),之后,加上⼀句set(CMAK_CXX_FLAGS "${CMAK_CXX_FLAGS} -Wno-error")-Wno-这个前缀,就是⽤来取消⼀个编译选项的然后,再add_subdirectory(B)-Wfatal-errors在发⽣第⼀个错误时中⽌编译。
gcc警告选项汇总
gcc警告选项汇总
警告是诊断消息,报告的结构本质上不是错误的,但是有风险或表明可能有错误。
以下与语言无关的选项不会启用特定的警告,但会控制GCC生成的诊断类型。
-fsyntax-only
检查代码中的语法错误,但除此之外不要做任何事情。
-fmax-errors= n
将错误消息的最大数量限制为n ,此时GCC会缓存,而不是尝试继续处理源代码。
如果n为0(默认值),则生成的错误消息数量不受限制。
如果还指定了-Wfatal-errors ,则重大错误优先于此选项。
-w
禁止所有警告消息。
-Werror
使所有的警告进入错误。
-Werror=
将指定的警告转换为错误。
附加警告的说明符; 例如-Werror =开关将由-Wswitch控制的警告转换为错误。
此开关采用否定形式,用于否定-针对特定警告的错误; 例如-Wno-error =开关使得-wswitch警告不是错误,即使在-Werror有效时也是如此。
每个可控警告的警告消息都包含控制警告的选项。
那么该选项可以与-Werror =和-Wno-error =一起使用,如上所述。
(可以使用-fno-diagnostics-show-option标志禁用警告消息中的选项打印。
)请注意,指定-Werror = foo会自动隐含-W foo 。
但是,-Wno-error = foo并不意味着什么。
常见gcc编译警告
1、warning: no newline at end of file在文件最后一行加上回车键解释:在《Rationale for the C99 standard》一文中,有C99的相关信息:A backslash immediately before a newline has long been used to continue string literals, as well as preprocessing command lines、In the interest of easing machine generation of C, and of transporting code to machines with restrictive physical line lengths, the C89 Committee generalized this mechanism to permit any token to be continued by interposing abackslash/newline sequence、c/c++代码的每一行后面有一个“结束符”,也就就是newline。
避免当被include的文件展开后,前一个文件的最后一行与后一个文件的第一行直接被连接成一行从而造成错误。
2、warning: comparison between pointer and integer解释:integer与pointer比较3、 warning: assignment discards qualifiers from pointer target type解释:赋值时,取消了右值的限定。
4、 warning: passing argument 1 of 'send' makes pointer from integer without a cast解释:函数send的第一个integer型参数没有强制转换为pointer型5、warning: comparison is always true due to limited range of data type解释:由于数据类型范围的限制,比较结果一直为真。
gcc编译报错解决方案
Gcc最基本的用法是∶gcc [options] [filenames] 其中options就是编译器所需要的参数,filenames给出相关的文件名称。
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。
如果不给出这个选项,gcc就给出预设的可执行文件a.out。
1.linker input file unused because linking not done我在Windows下使用SQLite编了个C++程序,在编写Makefile并使用cygwin 中的g++进行编译链接时遇到如下的错误:linker input file unused because linking not done我的语句是g++ -c a.cpp -lsqlite3到网上查了一下,问题出在链接数据库的语句不应出现在编译语句里面。
上面的语句里面有-c 即编译compile,所以命令会忽略掉所有的-l 链接库的命令。
而要链接数据库,应该在生成可执行文件时才使用。
正确的使用链接的语句应该是g++ a.o -L. -lsqlite3 -o exename2.Linux系统的头文件和库文件搜索路径**#include**的头文件,连结数据库,系统定义,总共有下列来源指定gcc去那找。
∙当初在编译时指定的(在~gcc/gcc/collect2.c:locatelib()∙写在specs内的(针对rpm包)∙后来用-D -I -L指定的∙gcc环境变量设定(编译的时候)∙ld.so的环境变量(这是run time的时候)头文件gcc 在编译时如何去寻找所需要的头文件:∙header file的搜寻会从-I开始∙然后找gcc的环境变量C_INCLUDE_PA TH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PA TH∙再找内定目录:o/usr/includeo/usr/local/includeo/usr/lib/gcc-lib/i386-linux/2.95.2/includeo/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3o/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include∙库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是o/usr/includeo prefix/includeo prefix/xxx-xxx-xxx-gnulibc/includeo prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include库文件cos()等函式库的选项要多加-lm∙编译的时候:gcc会去找-L∙再找gcc的环境变量LIBRARY_PATH∙再找内定目录/lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的运行时动态库的搜索路径1 在配置文件/etc/ld.so.conf中指定动态库搜索路径2 通过环境变量LD_LIBRARY_PA TH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)3 在编译目标代码时指定该程序的动态库搜索路径(还可以在编译目标代码时指定程序的动态库搜索路径。
GCC常见错误解析
GCC常见错误解析一、错误类型第一类∶C语法错误错误信息∶文件source.c中第n行有语法错误(syntex errror)。
这种类型的错误,一般都是C语言的语法错误,应该仔细检查源代码文件中第n行及该行之前的程序,有时也需要对该文件所包含的头文件进行检查。
有些情况下,一个很简单的语法错误,gcc会给出一大堆错误,此时要保持清醒的头脑,不要被其吓倒,必要的时候再参考一下C语言的基本教材。
第二类∶头文件错误错误信息∶找不到头文件head.h(Can not find include file head.h)。
这类错误是源代码文件中的包含头文件有问题,可能的原因有头文件名错误、指定的头文件所在目录名错误等,也可能是错误地使用了双引号和尖括号。
第三类∶档案库错误错误信息∶连接程序找不到所需的函数库,例如∶ld: -lm: No such file or directory.这类错误是与目标文件相连接的函数库有错误,可能的原因是函数库名错误、指定的函数库所在目录名称错误等,检查的方法是使用find命令在可能的目录中寻找相应的函数库名,确定档案库及目录的名称并修改程序中及编译选项中的名称。
第四类∶未定义符号错误信息∶有未定义的符号(Undefined symbol)。
这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题,这时需要使用档案库维护命令ar检查我们需要的库函数到底位于哪一个函数库中,确定之后,修改gcc 连接选项中的-l和-L项。
排除编译、连接过程中的错误,应该说这只是程序设计中最简单、最基本的一个步骤,可以说只是开了个头。
gcc毛病提示详解
conversion from %s to %s not supported by iconv”iconv 不支持从%s 到%s 的转换”iconv_open”iconv_open”no iconv implementation, cannot convert from %s to %s”没有iconv 的实现,无法从%s 转换到%s”character 0x%lx is not in the basic source character set\n”字符0x%lx 不在基本源字符集中\n”converting to execution character set”转换到可执行文件的字符集”character 0x%lx is not unibyte in execution character set”字符0x%lx 在执行字符集中不是单字节的”Character %x might not be NFKC”字符%x 可能不是NFKC”universal character names are only valid in C++ and C99″Unicode 字符名只在C++ 和C99 中有效”the meaning of ‘\\%c’ is different in traditional C”‘\\%c’的意义与在传统 C 中不同”In _cpp_valid_ucn but not a UCN”在_cpp_valid_ucn 中但不是一个UCN”incomplete universal character name %.*s”不完全的Unicode 字符名%.*s”%.*s is not a valid universal character”%.*s 不是一个有效的Unicode 字符”‘$’ in identifier or number”‘$’出现在标识符或数字中”universal character %.*s is not valid in an identifier”Unicode 字符%.*s 在标识符中无效”universal character %.*s is not valid at the start of an identifier”Unicode 字符%.*s 在标识符开头无效”converting UCN to source character set”将UCN 转换到源字符集”converting UCN to execution character set”将UCN 转换到执行字符集”the meaning of ‘\\x’ is different in traditional C”‘\\x’的意义与在传统 C 中不同”\\x used with no following hex digits”\\x 后没有16 进制数字”hex escape sequence out of range”16 进制转义序列越界”octal escape sequence out of range”8 进制转义序列越界”the meaning of ‘\\a’ is different in traditional C”‘\\a’的意义与在传统 C 中不同”non-ISO-standard escape sequence, ‘\\%c’”非ISO 标准的转义序列,‘\\%c’”unknown escape sequence: ‘\\%c’”未知的转义序列:‘\\%c’”unknown escape sequence: ‘\\%s’”未知的转义序列:‘\\%s’”converting escape sequence to execution character set”将转义序列转换到执行字符集”character constant too long for its type”字符常量大小超出其类型”multi-character character constant”多字节字符常量”empty character constant”空的字符常量”failure to convert %s to %s”无法从%s 转换到%s”extra tokens at end of #%s directive”#%s 指示的末尾有多余的标识符”#%s is a GCC extension”#%s 是一个GCC 扩展”#%s is a deprecated GCC extension”#%s 是一个已过时的GCC 扩展”suggest not using #elif in traditional C”建议在传统 C 中不使用#elif”traditional C ignores #%s with the # indented”当# 有缩进时传统 C 忽略#%s”suggest hiding #%s from traditional C with an indented #”建议使用缩进的# 以让#%s 对传统 C 不可见”embedding a directive within macro arguments is not portable”将一个指示嵌入宏参数中是不可移植的”style of line directive is a GCC extension”line 指示的风格是一个GCC 扩展”invalid preprocessing directive #%s”无效的预处理指示#%s”\”defined\” cannot be used as a macro name”“defined”不能被用作宏名”\”%s\” cannot be used as a macro name as it is an operator in C++”“%s”不能被用作宏名,因为它是C++ 中的一个操作符”no macro name given in #%s directive”#%s 指示中未给出宏名”macro names must be identifiers”宏名必须是标识符”undefining \”%s\”"取消对“%s”的定义”missing terminating > character”缺少结尾的> 字符”#%s expects \”FILENAME\” or ”#%s 需要\”FILENAME\”或”empty filename in #%s”#%s 中文件名为空”#include nested too deeply”#include 嵌套过深”#include_next in primary source file”#include_next 出现在主源文件中”invalid flag \”%s\” in line directive”line 指示中有无效的标记“%s””unexpected end of file after #line”#line 后未预期的文件结束”\”%s\” after #line is not a positive integer”#line 后的“%s”不是一个正整数”line number out of range”行号超出范围”\”%s\” is not a valid filename”“%s”不是一个有效的文件名”\”%s\” after # is not a positive integer”# 后的“%s”不是一个正整数”invalid #%s directive”无效的#%s 指示”registering pragmas in namespace \”%s\” with mismatched name expansion”在命名空间“%s”中注册pragma 时名称扩展不匹配”registering pragma \”%s\” with name expansion and no namespace”pragma “%s”被注册为一个命名扩展,而没有命名空间”registering \”%s\” as both a pragma and a pragma namespace”“%s”既被注册为一个pragma 又被注册为一个pragma 命名空间”#pragma %s %s is already registered”#pragma %s %s 已经被注册”#pragma %s is already registered”#pragma %s 已经被注册”registering pragma with NULL handler”pragma 注册为被NULL 处理”#pragma once in main file”#pragma once 出现在主文件中”invalid #pragma push_macro directive”无效的#pragma push_macro 指示”invalid #pragma pop_macro directive”无效的#pragma pop_macro 指示”invalid #pragma GCC poison directive”无效的#pragma GCC poison 指示”poisoning existing macro \”%s\”"对已存在的宏“%s”投毒”#pragma system_header ignored outside include file”#pragma system_heade 在包含文件外被忽略”cannot find source file %s”找不到源文件%s”current file is older than %s”当前文件早于%s”_Pragma takes a parenthesized string literal”_Pragma 需要一个括起的字符串字面常量”#else without #if”#else 没有匹配的#if”#else after #else”#else 出现在#else 后”the conditional began here”条件自此开始”#elif without #if”#elif 没有匹配的#if”#elif after #else”#elif 出现在#else 后”#: directives.c:1960#endif without #if”#endif 没有匹配的#if”missing ‘(‘ after predicate”谓词后缺少‘(’”missing ‘)’ to complete answer”完整的答案缺少‘)’”predicate’s answer is empty”谓词的答案为空”assertion without predicate”断言后没有谓词”predicate must be an identifier”谓词必须是一个标识符”\”%s\” re-asserted”重断言“%s””unterminated #%s”未终止的#%s”unterminated comment”未结束的注释”stdout”stdout”%s: %s”%s:%s”too many decimal points in number”数字中有太多小数点”fixed-point constants are a GCC extension”定点常量是一个GCC 扩展”invalid digit \”%c\” in binary constant”二进制常量中有无效数字“%c””invalid digit \”%c\” in octal constant”8 进制常量中有非法字符“%c””invalid prefix \”0b\” for floating constant”浮点常量的“0b”前缀无效”use of C99 hexadecimal floating constant”使用C99 式的16 进制浮点常量”exponent has no digits”指数部分没有数字”hexadecimal floating constants require an exponent”16 进制浮点常量需要指数部分”invalid suffix \”%.*s\” on floating constant”浮点常量的“%.*s”后缀无效”traditional C rejects the \”%.*s\” suffix”传统 C 不接受“%.*s”后缀”suffix for double constant is a GCC extension”双精度常量后缀是一个GCC 扩展”invalid suffix \”%.*s\” with hexadecimal floating constant”十六进制浮点常量的“%.*s”后缀无效”decimal float constants are a GCC extension”十进制浮点常量是一个GCC 扩展”invalid suffix \”%.*s\” on integer constant”整数常量的“%.*s”后缀无效”use of C++0x long long integer constant”使用C++0x long long 整数常量”imaginary constants are a GCC extension”虚数常量是一个GCC 扩展”binary constants are a GCC extension”二进制常量是一个GCC 扩展”integer constant is too large for its type”整数常量值超出其类型”integer constant is so large that it is unsigned”整数常量太大,认定为unsigned”missing ‘)’ after \”defined\”"“defined”后出现‘)’”operator \”defined\” requires an identifier”操作符“defined”需要一个标识符”(\”%s\” is an alternative token for \”%s\” in C++)”(在C++ 中“%s”会是“%s”的替代标识符)”this use of \”defined\” may not be portable”使用“defined”可能不利于移植”floating constant in preprocessor expression”浮点常量出现在预处理表达式中”imaginary number in preprocessor expression”预处理表达式中出现虚数”\”%s\” is not defined”“%s”未定义”assertions are a GCC extension”断言是一个GCC 扩展”assertions are a deprecated extension”断言是一个已过时的GCC 扩展”missing binary operator before token \”%s\”"标识符“%s”前缺少二元运算符”token \”%s\” is not valid in preprocessor expressions”标识符“%s”在预处理表达式中无效”missing expression between ‘(‘ and ‘)’”‘(’与‘)’之间缺少表达式”%s with no expression”%s 后没有表达式”operator ‘%s’ has no right operand”操作符‘%s’没有右操作数”operator ‘%s’ has no left operand”操作符‘%s’没有左操作数”‘:’ without preceding ‘?’”‘:’前没有‘?’”unbalanced stack in %s”%s 中堆栈不平衡”impossible operator ‘%u’”不可能的操作‘%u’”missing ‘)’ in expression”表达式中缺少‘)’”‘?’ without following ‘:’”‘?’后没有‘:’”integer overflow in preprocessor expression”预处理表达式中整数溢出”missing ‘(‘ in expression”表达式中缺少‘(’”the left operand of \”%s\” changes sign when promoted”“%s”的左操作数在提升时变换了符号”the right operand of \”%s\” changes sign when promoted”“%s”的右操作数在提升时变换了符号”traditional C rejects the unary plus operator”传统 C 不接受单目+ 运算符”comma operator in operand of #if”#if 操作数中出现逗号”division by zero in #if”#if 中用零做除数”NULL directory in find_file”find_file 中有NULL 目录”one or more PCH files were found, but they were invalid”找到一个或多个PCH 文件,但它们是无效的”use -Winvalid-pch for more information”使用-Winvalid-pch 以获得更多信息”%s is a block device”%s 是一个块设备”%s is too large”%s 过大”%s is shorter than expected”%s 短于预期”no include path in which to search for %s”没有包含路径可供搜索%s”Multiple include guards may be useful for:\n”多个防止重包含可能对其有用:\n”cppchar_t must be an unsigned type”cppchar_t 必须是无符号型”preprocessor arithmetic has maximum precision of %lu bits; target requires %lu bits”预处理算术的最高精度为%lu 位;目标需要%lu 位”CPP arithmetic must be at least as precise as a target int”CPP 算术必须至少具有目标int 的精度”target char is less than 8 bits wide”目标char 短于8 位”target wchar_t is narrower than target char”目录wchar_t 短于目标char”target int is narrower than target char”目标int 短于目标char”CPP half-integer narrower than CPP character”CPP 半整数短于CPP 字符”CPP on this host cannot handle wide character constants over %lu bits, but the target requires %lu bits”在此宿主机上,CPP 不能处理长于%lu 位的宽字符常量,但目标需要%lu 位”backslash and newline separated by space”反斜杠和换行为空格所分隔”backslash-newline at end of file”反斜杠续行出现在文件末尾”trigraph ??%c converted to %c”三元符??%c 转换为%c”trigraph ??%c ignored, use -trigraphs to enable”三元符??%c 被忽略,请使用-trigraphs 来启用”\”/*\” within comment”“/*”出现在注释中”%s in preprocessing directive”预处理指示中出现%s”null character(s) ignored”忽略空字符”`%.*s’ is not in NFKC”‘%.*s’不在NFKC 中”`%.*s’ is not in NFC”‘%.*s’不在NFC 中”attempt to use poisoned \”%s\”"试图使用有毒的“%s””__VA_ARGS__ can only appear in the expansion of a C99 variadic macro”__VA_ARGS__ 只能出现在C99 可变参数宏的展开中”identifier \”%s\” is a special operator name in C++”标识符“%s”是C++ 中的一个特殊操作符”raw string delimiter longer than 16 characters”原始字符串分隔符长过16 个字符”invalid character ‘%c’ in raw string delimiter”原始字符串分隔符中有无效字符‘%c’”unterminated raw string”未终止的原始字符串”null character(s) preserved in literal”空字符将保留在字面字符串中”missing terminating %c character”缺少结尾的%c 字符”C++ style comments are not allowed in ISO C90″C++ 风格的注释在ISO C90 中不被允许”(this will be reported only once per input file)”(此警告为每个输入文件只报告一次)”multi-line comment”多行注释”unspellable token %s”无法拼出的标识符%s”macro \”%s\” is not used”宏“%s”未被使用”invalid built-in macro \”%s\”"无效的内建宏“%s””could not determine file timestamp”无法决定文件的时间戳”could not determine date and time”无法决定日期与时间”__COUNTER__ expanded inside directive with -fdirectives-only”带-fdirectives-only 时__COUNTER__ 在指示中扩展”invalid string literal, ignoring final ‘\\’”无效的字面字符串,忽略最后的‘\\’”pasting \”%s\” and \”%s\” does not give a valid preprocessing token”毗连“%s”和“%s”不能给出一个有效的预处理标识符”ISO C99 requires rest arguments to be used”ISO C99 需要使用剩余的参数”macro \”%s\” requires %u arguments, but only %u given”宏“%s”需要%u 个参数,但只给出了%u 个”macro \”%s\” passed %u arguments, but takes just %u”宏“%s”传递了%u 个参数,但只需要%u 个”unterminated argument list invoking macro \”%s\”"调用宏“%s”时参数列表未终止”function-like macro \”%s\” must be used with arguments in traditional C”类似函数的宏“%s”在传统 C 中必须与参数一起使用”invoking macro %s argument %d: empty macro arguments are undefined in ISO C90 and ISO C++98″调用宏%s 的参数%d:空的宏参数未被ISO C90 和ISO C++98 定义”duplicate macro parameter \”%s\”"重复的宏参数“%s””\”%s\” may not appear in macro parameter list”“%s”不能出现在宏参数列表中”macro parameters must be comma-separated”宏参数必须由逗号隔开”parameter name missing”缺少形参名”anonymous variadic macros were introduced in C99″匿名可变参数宏在C99 中被引入”ISO C does not permit named variadic macros”ISO C 不允许有名的可变参数宏”missing ‘)’ in macro parameter list”在宏参数表中缺少‘)’”‘##’ cannot appear at either end of a macro expansion”‘##’不能出现在宏展开的两端”ISO C99 requires whitespace after the macro name”ISO C99 要求宏名后必须有空白”missing whitespace after the macro name”宏名后缺少空白”‘#’ is not followed by a macro parameter”‘#’后没有宏参数”\”%s\” redefined”“%s”重定义”this is the location of the previous definition”这是先前定义的位置”macro argument \”%s\” would be stringified in traditional C”宏参数“%s”将在传统 C 中被字符串化”invalid hash type %d in cpp_macro_definition”cpp_macro_definition 中有无效的散列类型%d”while writing precompiled header”在写入预编译头时”%s: not used because `%.*s’ is poisoned”%s:未使用因为‘%.*s’已被投毒”%s: not used because `%.*s’ not defined”%s:未使用因为‘%.*s’未定义”%s: not used because `%.*s’ defined as `%s’ not `%.*s’”%s:未使用因为‘%.*s’被定义为‘%s’而非‘%*.s’”%s: not used because `%s’ is defined”%s:未使用因为‘%s’已定义”%s: not used because `__COUNTER__’ is invalid”%s:未使用因为‘__COUNTER__’无效”while reading precompiled header”在读取预编译头时”detected recursion whilst expanding macro \”%s\”"展开宏“%s”时检测到递归”syntax error in macro parameter list”宏参数列表语法错误”#~ warning: ”#~ 警告:”#~ internal error: ”#~ 内部错误:”#~ error: ”#~ 错误:”#~ In file included from %s:%u”#~ 在包含自%s:%u 的文件中”#~ ”#~ “,\n”#~ ” from %s:%u”#~ ”#~ “,\n”#~ ”从%s:%u”#~ no newline at end of file”#~ 文件未以空白行结束”。
gcc 警告安全级别
gcc 警告安全级别一、-Wall级别下的警告-Wall是GCC中一个常用的警告选项,它会启用大多数的警告信息。
在这个级别下,GCC会对代码中的潜在问题进行提示,开发者可以根据这些警告信息进行代码的优化和改进。
例如,当我们在代码中使用了未声明的变量时,GCC会给出警告信息,提示我们可能存在的问题。
这种警告可以帮助我们发现代码中的潜在错误,并及时修复。
在-Wall级别下,GCC还会对一些常见的编程错误进行提示,比如使用未初始化的变量、函数返回值未使用等。
这些警告信息可以帮助我们提高代码的可靠性和健壮性。
二、-Wextra级别下的警告-Wextra是GCC中的另一个常用的警告选项,它启用了更多的警告信息。
在这个级别下,GCC会对代码中的一些潜在问题进行更加详细的提示。
例如,当我们在代码中使用了不安全的函数时,GCC会给出警告信息,提示我们可能存在的安全风险。
这种警告可以帮助我们避免使用一些已知的不安全函数,从而提高代码的安全性。
在-Wextra级别下,GCC还会对代码中的一些潜在的逻辑错误进行提示。
例如,当我们在条件语句中使用了错误的比较符号时,GCC会给出警告信息,帮助我们发现和修复这些潜在的逻辑错误。
三、-Werror级别下的警告-Werror是GCC中的一个特殊的警告选项,它会将所有的警告信息视为错误,即在编译过程中如果出现了任何警告信息,GCC都会将其视为错误并停止编译。
在使用-Werror选项时,我们需要对代码中的所有警告信息进行仔细的检查和处理,确保代码的质量和可靠性。
这种方式可以帮助我们及时发现和解决代码中的问题,并提高代码的可维护性。
然而,使用-Werror选项也需要谨慎,因为有些警告信息可能并不是真正的问题,而是编译器的一些限制或者特性。
在处理这些警告信息时,我们需要仔细分析,并根据实际情况进行调整。
四、-Wno-<警告类型>选项除了上述提到的几个常用的警告选项外,GCC还提供了一些特定的警告选项,可以根据实际需求进行选择和使用。
对于GCC警告选项的理解
dereferencing type-punned pointer will break strict-aliasing rules 警告信息跟 优化选项-fstrict-aliasing 有关。当开启这个优化选项时,可能优化会导致源 代码中部分语句缺失,而造成系统工作不正常,所以就所有的违反 strictaliasing rules 原则的地方加了条这个警告信息,提醒读者检查这个地方的代 码,看看是不是如果优化后会导致部分语句工作不正常 同时这个信息提示还有另外一个目的,两个不同类型的指针指向同一个地 址时,极有可能会导致代码编写出错(比如犯大小端的错误,还有地址字节对 齐的错误),所以这个警告信息还有这一层的目的。
3 ../SRC/libpjmacl/pjmacl_pjm.c:2867: 警告: no previous declaration for pjmacl_get_node_pri_U pjmacl_get_node_pri_U 如果为外部函数的话,就应该有个声明加到类似 pjsd_prt.h 中 4 ../SRC/libpjmfep/pjmfep_exec.c:406: 警告: implicit declaration of function pj/libpjmfep/pjmfep_exec.c:406: 警告: nested extern declaration of pjmfep_evc_queue_init pjmfep_evc_queue_init 函数就没有被声明过,而且如果定义文件和引用该 函数文件不一样时,引用该函数的文件也没有提前用 extern 声明该函数 5 ../SRC/pjmd/pjmd_conff.c:1053: 警告: passing argument 1 of set_rscGrpNode_type4 discards qualifiers from pointer target type
GCC警告选项例解
GCC警告选项例解程序员是追求完美的一族,即使是一般的程序员大多也都不想看到自己的程序中有甚至那么一点点的瑕疵。
遇到任意一条编译器警告都坚决不放过。
有人会说:我们可以使用比编译器更加严格的静态代码检查工具,如splint。
这个建议也很不错。
不过lint工具使用起来较繁琐,有时候还需要记住一些特定符号并插入到你自己的代码中才行,门槛较高,这也让很多人止步于此。
那么我们就从此放弃么?不,如今的编译器做得都很好,它可以帮助我们的找到绝大多数可能出现问题的代码,前提是你要学会控制编译器去找到这些问题代码,而熟悉编译器的警告选项恰恰是体现控制力的好方法。
当你可以自如控制编译器警告输出的时候,你就算是'入道'了,同时你对语言的理解也更进一步了。
有人说:我就是用一个-Wall选项就可以了,一般选手可以这么做,而且他可以不知道-Wall会跟踪哪些类型的问题;但是高级选手是不会只使用-Wall的,他会把每条警告都研究的很透彻,会在Makefile中列出他想让编译器输出哪些类型的警告以替代-Wall,他会屏蔽掉那些对他的代码'毫无用处'的警告(很可能他使用了编译器对语言的扩展功能),他会有个和编译器交流的过程。
俗话说:'工欲善其事,必先利其器',一直在工作中使用GNU C编译器(以下简称GCC),这里对GCC的一些警告选项细致的分析,并列举几个简单的例子[注1]供分析参考。
1. -Wall集合警告选项我们平时可能大多数情况只使用-Wall编译警告选项,实际上-Wall选项是一系列警告编译选项的集合。
下面逐一分析这一集合中的各个选项:[-Wchar-subscripts]如果数组使用char类型变量做为下标值的话,则发出警告。
因为在某些平台上char可能默认为signed char,一旦溢出,就可能导致某些意外的结果。
e.g./* test_signed_char.c */#includeint main () {char c = 255; // 我们以为char是无符号的,其范围应该是[0,255]int i = 0;int a[256];for (i = 0; i < 256; i++) {a[i] = 1;}printf("%d\n", c); // 我们期待输出255printf("%d\n", a[c]); // 我们期待输出1printf("%d\n", a[255]);return 0;}gcc -Wchar-subscripts test_signed_char.ctest_signed_char.c: In function `main':test_signed_char.c:13: warning: array subscript has type `char'其输出结果:-1-41974761从输出结果来看Solaris 9/gcc 3.2上char默认实现类型为signed char;在Windows XP/gcc-3.4.2上也是一样。
最新GCC编译器选项及优化提示
G C C编译器选项及优化提示GCC编译器选项及优化提示GCC编译器选项及优化提示2010-08-01 19:41很多弟兄可能都很关心如何优化编译自己的程序,虽然本人不赞成"骨灰"玩法,却也不得不承认这是掌握gcc的绝佳途径;因此献上此帖,以供各位玩家参考,绝对原创噢=大多数程序和库在编译时默认的优化级别是"2"(使用gcc选项:"-O2")并且在Intel/AMD平台上默认按照i386处理器来编译。
如果你只想让编译出来的程序运行在特定的平台上,就需要执行更高级的编译器优化选项,以产生只能运行于特定平台的代码。
一种方法是修改每个源码包中的Makefile文件,在其中寻找CFLAGS和CXXFLAGS变量(C和C++编译器的编译选项)并修改它的值。
一些源码包比如binutils,gcc,glibc等等,在每个子文件夹中都有Makefile文件,这样修改起来就太累了!另一种简易做法是设置CFLAGS和CXXFLAGS环境变量。
大多数configure 脚本会使用这两个环境变量代替Makefile文件中的值。
但是少数configure脚本并不这样做,他们必须需要手动编辑才行。
为了设置CFLAGS和CXXFLAGS环境变量,你可以在bash中执行如下命令(也可以写进.bashrc以成为默认值):export CFLAGS="-O3-march="&&CXXFLAGS=$CFLAGS这是一个确保能够在几乎所有平台上都能正常工作的最小设置。
"-march"选项表示为特定的cpu类型编译二进制代码(不能在更低级别的cpu上运行),Intel通常是:pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium-m,prescott,nocona说明:pentium3m/pentium4m是笔记本用的移动P3/P4;pentium-m是迅驰I/II代笔记本的cpu;prescott是带SSE3的P4(以滚烫到可以煎鸡蛋而闻名);nocona则是最新的带有EMT64(64位)的P4(同样可以煎鸡蛋)AMD通常是:k6,k6-2,k6-3,athlon,athlon-tbird,athlon-xp,athlon-mp,opteron,athlon64,athlon-fx用AMD的一般都是DIYer,就不必解释了吧。
gcc编译选项分析
小知识
可以看出,该选项并没有发现”long long”这个无效数据类型的错误。
∙“-pedantic”
允许发出ANSI C标准所列的全部警告信息,同样也保证所有没有警告的程序都是符合ANSI C标准的。
其运行结果如下所示:
[root@localhost Gcc]# Gcc –pedantic warning.c –o warning
warning.c: 在函数“main”中:
warning.c:5 警告:ISO C90不支持“long long”
warning.c:7 警告:在无返回值的函数中,“return”带返回值
warning.c:4 警告:“main”的返回类型不是“int”
可以看出,使用该选项查看出了”long long”这个无效数据类型的错误。
∙“-Wall”
允许发出Gcc能够提供的所有有用的报警信息。
该选项的运行结果如下所示:[root@localhost Gcc]# Gcc –Wall warning.c –o warning
warning.c:4 警告:“main”的返回类型不是“int”
warning.c: 在函数”main”中:
warning.c:7 警告:在无返回值的函数中,”return”带返回值
warning.c:5 警告:未使用的变量“tmp”
使用“-Wall”选项找出了未使用的变量tmp,但它并没有找出无效数据类型的错误。
另外,Gcc还可以利用选项对单独的常见错误分别指定警告,有关具体选项的含义感兴趣的读者可以查看Gcc手册进行学习。
(3)优化选项。
GCC的几个重要选项解释
GCC的几个重要选项解释GCC的几个重要选项解释详细可见:[GNU Compiler Collection (GCC)]Option-Summary.html-c 编译或者汇编代码,但是不链接-S 在编译之后停止,但不汇编-E 预处理后停止,但不编译-o 指定输出文件的名称-v 显示编译的每个阶段使用的命令-std 指定要用的语言标准-g 产生调试信息-pg 产生额外信息,被gprof用来做profilling-O 优化可执行代码-W 设置编译器的警报级别-pedantic以ANSI/ISO C标准列出的所有警告,不符合该语言标准的地方将产生相应的警告信息-I 指定文件包含的目录-L 指定库目录(编译时的库搜索目录)-D 预定义在源代码中出现的宏-U 取消所有定义的宏-f 指定用来控制编译器行为的选项-m 指定与硬件相关的选项GCC相关信息查看-help 显示此帮助说明-target-help 显示目标机器特定的命令行选项-help={target|optimizers|warnings|params|[^]{joined|separate|un documented}}[,...]显示特定类型的命令行选项(使用‘-v --help’显示子进程的命令行参数)-version 显示编译器版本信息-dumpspecs 显示所有内建 spec 字符串-dumpversion 显示编译器的版本号-dumpmachine 显示编译器的目标处理器-print-search-dirs 显示编译器的搜索路径-print-libgcc-file-name 显示编译器伴随库的名称-print-file-name=<库> 显示 <库> 的完整路径-print-prog-name=<程序> 显示编译器组件 <程序> 的完整路径-print-multi-directory 显示不同版本 libgcc 的根目录-print-multi-lib 显示命令行选项和多个版本库搜索路径间的映射-print-multi-os-directory 显示操作系统库的相对路径-print-sysroot 显示目标库目录-print-sysroot-headers-suffix 显示用于寻找头文件的sysroot 后缀目前了解的GCC相关具体选项-fpic用于生成位置无关代码,位置无关码的作用:1、程序在运行期间动态加载到内存中;2、程序在不同场合与不同程序组合后加载到内存(一般用于动态链接库)3、在运行期间不同地址相互之间的映射;(如bootloader)简言之,位置无关码就是可以在进程的任意内存位置执行的目标码,动态链接库必须使用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
GCC警告选项例解程序员是追求完美的一族,即使是一般的程序员大多也都不想看到自己的程序中有甚至那么一点点的瑕疵。
遇到任意一条编译器警告都坚决不放过。
有人会说:我们可以使用比编译器更加严格的静态代码检查工具,如splint。
这个建议也很不错。
不过lint工具使用起来较繁琐,有时候还需要记住一些特定符号并插入到你自己的代码中才行,门槛较高,这也让很多人止步于此。
那么我们就从此放弃么?不,如今的编译器做得都很好,它可以帮助我们的找到绝大多数可能出现问题的代码,前提是你要学会控制编译器去找到这些问题代码,而熟悉编译器的警告选项恰恰是体现控制力的好方法。
当你可以自如控制编译器警告输出的时候,你就算是'入道'了,同时你对语言的理解也更进一步了。
有人说:我就是用一个-Wall选项就可以了,一般选手可以这么做,而且他可以不知道-Wall会跟踪哪些类型的问题;但是高级选手是不会只使用-Wall的,他会把每条警告都研究的很透彻,会在Makefile中列出他想让编译器输出哪些类型的警告以替代-Wall,他会屏蔽掉那些对他的代码'毫无用处'的警告(很可能他使用了编译器对语言的扩展功能),他会有个和编译器交流的过程。
俗话说:'工欲善其事,必先利其器',一直在工作中使用GNU C编译器(以下简称GCC),这里对GCC的一些警告选项细致的分析,并列举几个简单的例子[注1]供分析参考。
1. -Wall集合警告选项我们平时可能大多数情况只使用-Wall编译警告选项,实际上-Wall选项是一系列警告编译选项的集合。
下面逐一分析这一集合中的各个选项:[-Wchar-subscripts]如果数组使用char类型变量做为下标值的话,则发出警告。
因为在某些平台上char可能默认为signed char,一旦溢出,就可能导致某些意外的结果。
e.g./* test_signed_char.c */#includeint main () {char c = 255; // 我们以为char是无符号的,其范围应该是[0,255]int i = 0;int a[256];for (i = 0; i < 256; i++) {a[i] = 1;}printf("%d\n", c); // 我们期待输出255printf("%d\n", a[c]); // 我们期待输出1printf("%d\n", a[255]);return 0;}gcc -Wchar-subscripts test_signed_char.ctest_signed_char.c: In function `main':test_signed_char.c:13: warning: array subscript has type `char'其输出结果:-1-41974761从输出结果来看Solaris 9/gcc 3.2上char默认实现类型为signed char;在Windows XP/gcc-3.4.2上也是一样。
Windows上的输出结果:-116 (随机值)1[-Wcomment]当'/*'出现在'/* ... */'注释中,或者'\'出现在'// ...'注释结尾处时,使用-Wcomment会给出警告。
不要小觑这些马虎代码,它很可能会影响程序的运行结果。
如下面的例子:e.g./** test_comment.c* gcc -Wcomment test_comment.c*/#includeint main() {int a = 1;int b = 2;int c = 0; // ok just test\c = a + b;/** 这里我们期待c = 3* /* 但实际上输出c = 0*/printf("the c is %d\n", c);return 0;}gcc -Wcomment test_comment.ctest_comment.c:10:30: warning: multi-line commenttest_comment.c:15:12: warning: "/*" within comment输出:the c is 0[-Wformat]检查printf和scanf等格式化输入输出函数的格式字符串与参数类型的匹配情况,如果发现不匹配则发出警告。
某些时候格式字符串与参数类型的不匹配会导致程序运行错误,所以这是个很有用的警告选项。
e.g./** test_format.c*/#includeint main() {long l = 1;double d = 55.67;printf("%d\n", l);printf("%d\n", d);return 0;}gcc -Wformat test_format.ctest_format.c: In function `main':test_format.c:10: warning: int format, long int arg (arg 2)test_format.c:11: warning: int format, double arg (arg 2)输出:11078711746[-Wimplicit]该警告选项实际上是-Wimplicit-int和-Wimplicit-function-declaration两个警告选项的集合。
前者在声明函数却未指明函数返回类型时给出警告,后者则是在函数声明前调用该函数时给出警告。
e.g./** test_implicit.c*/#includeadd(int a, int b) { //函数没有声明返回类型return a + b;}int test() {int a = 0;int b = 0;int c = 0;int d = 0;c = add(a, b);d = sub(a, b); //未声明sub的函数原型return 0;}gcc -Wimplicit -c test_implicit.ctest_implicit.c:7: warning: return type defaults to `int'test_implicit.c: In function `test':test_implicit.c:18: warning: implicit declaration of function `sub'[-Wmissing-braces]当聚合类型或者数组变量的初始化表达式没有'充分'用括号{}括起时,给出警告。
文字表述很难理解,举例说明则清晰些。
看下面的例子:e.g./** test_missing_braces.c*/struct point {int x;int y;};struct line {struct point start;struct point end;};typedef struct line line;int main() {int array1[2][2] = {11, 12, 13, 14};int array2[2][2] = {{11, 12}, {13, 14}}; // okline l1 = {1, 1, 2, 2};line l2 = {{2, 2}, {3, 3}}; // okreturn 0;}gcc -Wmissing-braces test_missing_braces.ctest_missing_braces.c: In function `main':test_missing_braces.c:19: warning: missing braces around initializertest_missing_braces.c:19: warning: (near initialization for `array1[0]')test_missing_braces.c:21: warning: missing braces around initializertest_missing_braces.c:21: warning: (near initialization for `l1.start')[-Wparentheses]这是一个很有用的警告选项,它能帮助你从那些看起来语法正确但却由于操作符优先级或者代码结构'障眼'而导致错误运行的代码中解脱出来。
好长的一个长句,还是看例子理解吧!:)e.g./** test_parentheses.c* gcc -Wparentheses test_parentheses.c*/#includeint main() {int a = 1;int b = 1;int c = 1;int d = 1;if (a && b || c) { // 人们很难记住逻辑操作符的操作顺序,所以编译器建议加上();}if (a == 12)if (b)d = 9;elsed = 10; //从代码的缩进上来看,这句仿佛是if (a == 12)的else分支printf("the d is %d\n", d); //期待d = 10, 而结果却是1return 0;}gcc -Wparentheses test_parentheses.ctest_parentheses.c: In function `main':test_parentheses.c:13: warning: suggest parentheses around && within ||test_parentheses.c:17: warning: suggest explicit braces to avoid ambiguous `else'输出:the d is 1[-Wsequence-point]关于顺序点(sequence point),在C标准中有解释,不过很晦涩。
我们在平时编码中尽量避免写出与实现相关、受实现影响的代码便是了。
而-Wsequence-point选项恰恰可以帮我们这个忙,它可以帮我们查出这样的代码来,并给出其警告。
e.g./** test_sequence_point.c* gcc -Wsequence-point test_sequence_point.c*/#includeint main() {int i = 12;i = i--;printf("the i is %d\n", i);return 0;}gcc -Wsequence-point test_sequence_point.ctest_sequence_point.c: In function `main':test_sequence_point.c:10: warning: operation on `i' may be undefined在两个平台上给出的编译警告都是一致的,但是输出结果却大相径庭。