当前位置:首页 > 智能硬件 > 智能硬件
[导读]c编译器是程序运行的基础,一款好的c编译器具备优良性能。目前,GCC是三大主流c编译器之一。对于这款c编译器,可能大家并非十分了解。本文中,将为大家介绍gcc常见的编译警告以及解决方法。如果你对这款c编译器比较感兴趣,不妨继续往下看哦。

c编译器是程序运行的基础,一款好的c编译器具备优良性能。目前,GCC是三大主流c编译器之一。对于这款c编译器,可能大家并非十分了解。本文中,将为大家介绍gcc常见的编译警告以及解决方法。如果你对这款c编译器比较感兴趣,不妨继续往下看哦。

GCC有很多的编译选项,警告选项;指定头文件、库路径;优化选项。本文针整理一下GCC的警告选项以及gcc编译警告整理和解决方法为中心而展开的讨论。

一、GCC编译警告总概

-w

禁止编译警告的打印。这个警告不建议使用。大约2012年底,公司代码进行一次大重构,另外从Codeblock集成开发环境转向Makefile管理,Makefile里面默认使用了-w,因而代码一直没有警告,今年个别项目开发中发现一些代码笔误导致的BUG,而这些问题可以从编译警告中知道。前几个月,领导安排我来fix这些警告。为了自己,为了后人,不建议使用-w选项。

-Werror

将所有的警告当成错误处理。此选项谨慎建议加上。有的开源库警告很多(大名鼎鼎的ffmpeg也有很多警告呢),一一改掉耗时耗人力,必要性也不大。最后,公司代码加入了一个开源库,里面有很多代码警告,可能领导又安排我来fix了。

-Wfatal-errors

遇到第一个错误就停止,减少查找错误时间。建议加上。很多人遇到错误,没有意识到从第一个开始排查。不管是编译错误,还是程序运行出错,从最开始的错误查起,是个好的做法。

-Wall开启“所有”的警告。强烈建议加上,并推荐该选项成为共识。如case语句没有default处理,有符号、无符号处理,未使用变量(特别是函数有大量未使用的数组,占用栈空间,测试发现,开辟一个未使用的8MB的数组,程序有coredump),用%d来打印地址,或%s打印int值,等,都可以发出警告。

-Wextra

除-Wall外其它的警告。建议加上。

在GCC编译时,加上必要的警告选项,可以避免很多低级错误引发的问题,我就在实际工程代码中遇到用“==”来赋值,我自己写的代码也出现过把“=”当成判断的。但是,有些错误却不是用GCC选项能解决的。比如一般项目都会自定义调试信息打印函数,但在处理可变参数类型时,往往不注意。可参考文章《一个可变参数类型检查的示例》。

二、GCC编译警告细化

上面只是大概讲几个重要的选项。由于GCC的警告选项太多了,下面尽自己能力写一下。

-Wall选项,顾名思义,就是“所有”的意思,它包括:

[html] view plain copy-Wall包括:

-Waddress

-Warray-bounds=1 (only with -O2)

-Wc++11-compat -Wc++14-compat

-Wchar-subscripts

-Wenum-compare (in C/ObjC; this is on by default in C++)

-Wimplicit-int (C and ObjecTIve-C only)

-Wimplicit-funcTIon-declaraTIon (C and ObjecTIve-C only)

-Wbool-compare

-Wduplicated-cond

-Wcomment

-Wformat

-Wmain (only for C/ObjC and unless -ffreestanding)

-Wmaybe-uninitialized

-Wmissing-braces (only for C/ObjC)

-Wnonnull

-Wopenmp-simd

-Wparentheses

-Wpointer-sign

-Wreorder

-Wreturn-type

-Wsequence-point

-Wsign-compare (only in C++)

-Wstrict-aliasing

-Wstrict-overflow=1

-Wswitch

-Wtautological-compare

-Wtrigraphs

-Wuninitialized

-Wunknown-pragmas

-Wunused-function

-Wunused-label

-Wunused-value

-Wunused-variable

-Wvolatile-register-var

但不要被它的表面意思迷惑,要不,怎么还会有-Wextra呢。-Wextra包括(有几个选项重复了,不懂原因):

[html] view plain copy-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

-Wshift-negative-value

-Wunused-parameter (only with -Wunused or -Wall)

-Wunused-but-set-parameter (only with -Wunused or -Wall)

-Wchar-subscripts:

使用char类作为数组下标(因为char可能是有符号数)

-Wcomment:

注释使用不规范。如“/* */”注释中还包括“/*”。我在项目源码发现过,不止一处。

-Wmissing-braces

括号不匹配。在多维数组的初始化或赋值中经常出现。下面a没有完整被初始化,b完整初始化:

int a[2][2] = { 0, 1, 2, 3 };

int b[2][2] = { { 0, 1 }, { 2, 3 } };

-Wparentheses

括号不匹配,在运算符操作或if分支语句中,可能会出现此警告。

如“a&&b||c^d”会出现警告。下面代码片段也会有警告

{

if (a)

if (b)

foo ();

else

bar (); // 这个else实际是if (b)的分支,不是if (a),因此,要用括号来表明其属于哪个分支

}

这类bug隐藏得深,建议显式地加上括号。

-Wsequence-point

如出现i=i++这类代码,则报警告。-Wall默认有该警告

-Wswitch-defaultcase

没有default时,报警告

-Wunused-but-set-parameter

设置了但未使用的参数警告

-Wunused-but-set-variable

设置了但未使用的变量警告

-Wunused-function

声明但未使用函数

-Wunused-label

未使用的标签,比如用goto会使用label,但在删除goto语句时,忘了删除label。

-Wunused-variable

未使用的变量

-Wmaybe-uninitialized

变量可能没有被初始化。特别是在有if语句或switch语句中,最好在声明变量时加上初始化。

下面代码片段中,当y不是1、2、3时,x没有明确的值,是不安全的。

{

int x;

switch (y)

{

case 1: x = 1;

break;

case 2: x = 4;

break;

case 3: x = 5;

}

foo (x);

}

-Wfloat-equal

对浮点数使用等号,这是不安全的。

{

float d = 2.0;

if (d == i)

{

。。。

}

}

-Wreturn-type

函数有返回值,但函数体个别地方没有返回值(特别是有if判断,可能忘记在else添加返回值)。

int foo()

{

if(a==1)

{

return ok;

}

// no return here

}

-Wpointer-sign

指针有符号和无符号的错误传参。如函数使用unsigned char*,但传入char*指针。

-Wsign-compare

有符号和无符号比较。

-Wconversion-null

-Wsizeof-pointer-memaccess

在sizeof中经常出现,下面代码片段中,this为指针,4字节,无法保证完整初始化类。

memset(this, 0, sizeof(this));

-Wreorder

C++出现,构造函数中成员变量初始化与声明的顺序不一致。

-Woverflow

范围溢出。

-Wshadow

局部变量覆盖参数、全局变量,报警告

三、常见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

解释:赋值时,取消了右值的限定。

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

解释:由于数据类型范围的限制,比较结果一直为真。

6、warning: initialization from incompatible pointer type

解释:不兼容指针类型的初始化

7、 warning: return makes pointer from integer without a cast

解释:return使integer转换为pointer,没有加强制类型转换。

8、warning: incompatible implicit declaration of built-in function ‘printf’

解释:与内置的printf函数隐士声明不兼容。

9、warning: initialization discards qualifiers from pointer target type

解释:initialization取消了指针目标类型的限定。

10、warning: comparison is always false due to limited range of data type

由于类型限制,比较一直是假

11、warning: assignment from incompatible pointer type

不兼容的指针间赋值

12、warning: passing argument 1 of ‘mes_read_time’ discards qualifiers from pointer target type12、

mes_函数第一个参数的传递,丢弃了指针目标类型限定。

13、warning: “protocol_type” redefined

——type重定义

14、warning: ‘return’ with a value, in function returning void

在void返回类型的函数中,return返回值。

15、error: expected expression before ‘else’

else之前无表达式。

16、error: lvalue required as left operand of assignment

左值问题。

17、error: invalid storage class for function ‘XXXXXX’

在文件的某个地方,丢失了一个大括号‘}’。

四、Linux编程gcc编译器禁止所有警告和显示所有警告

编译程序的时候,经常会出现警告。不过对于很多经过,程序员经常无视它的存在,甚至觉得警告挺烦人的。

在linux编译程序时,我们可以很方便的禁止所有警告和显示所有警告。

gcc编译器命令选项-Wall 用来显示所有警告信息,而-w则用来禁止所有警告的显示。默认是显示警告的。

警告不是错误,所以错误会正常的显示。

下面是命令的使用示例:

显示所有警告信息

gcc hello.c -o hello -Wall

禁止所有警告信息

gcc hello.c -o hello -w

这是linux编程需要知道的,就在这里记录一下,以便以后查询。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

如果你是在Linux下做开发,你就必须知道Makefile是什么东西,如果不知道那就可以说你不是一个合格的Linux开发工程师,因为Makefile是必备的一项技能。那么,Makefile到底有什么作用呢?首先,gcc大...

关键字: Linux Makefile gcc

众所周知,LLVM的Clang C / C ++编译器比GCC提供更快的编译速度。 但是,新版本的GCC中的编译速度有所提高。

关键字: gcc Linux llvm

上篇文章中,小编对Turbo c编译器已做部分介绍。本文中,小编将对Turbo c编译器余下内容加以讲解。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 turbo 指数

为增进大家对c编译器的认识,本文将对Turbo C c编译器予以讲解。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 turbo 指数

本文中,小编将对c编译器和c编辑器的区别予以介绍。如果你对c编译器具有兴趣,不妨继续往下阅读哦。

关键字: c编译器 指数 c编辑器

最近发布的 GCC 10 编译器已对 C++20 的主要功能协程(Co-Routines)进行了初始支持,但是除非显式地开启该选项,否则并不会启用此功能。当 GCC 10 在 C++20 模式(std

关键字: gcc

许多朋友经常混淆c编译器和c编辑器,注意,c编译器的作用在于编译,而c编辑器在于编写代码。对于c编译器,小编曾带来诸多文章。但有网友提问,有没有较为推荐的c编译器。为解决大家的疑问,本文将对6款c编译器予以介绍,大家可以...

关键字: c编译器 指数 编译器

c编译器每天都在被使用,但对c编译器十分了解的人却不多,而对c编译器编译过程有所认知的朋友更是少之又少。在上篇文章中,小编对c编译器的工作过程有所讲解。本文中,为继续增进大家对c编译器的讲解,将对编译器工作过程的余下步骤...

关键字: c编译器 指数 编译器

c编译器的问世是程序界的里程碑之一,没有c编译器,c程序将无法运行。由此可见,c编译器尤为重要。为增进大家对c编译器的了解,本文将带来c编译器的通识篇,以使大家能够了解编译器的运行过程。此外,本文仅为上篇,剩余内容将在后...

关键字: c编译器 指数 编译器

对于c编译器,很多朋友均有所了解。往期文章中,小编为大家带来过诸多c编译器文章。在这篇c编译器相关文章中,小编将介绍如何基于SDCC c编译器开发微控制器。如果你对c编译器的应用同样存在兴趣,不妨继续往下阅读哦。

关键字: c编译器 sdcc 微控制器 指数
关闭
关闭