2012年01月24日
GCCでunsignedの変数を0と比較したときにwarningを出すオプション
昨日、自分で修正したプログラムが意図した通りに動作しなくて少し悩んだのですが、それはunsignedの型の変数に負数を代入して、0と比較している部分が正しく動かなかったためでした。unsignedの型の変数は0より小さくなることはありません。
でも、こんなケースではgccはwarningを出して教えてくれたはず。実はオプションの指定が必要でした。
サンプルプログラム
以下のプログラムではxがどんな値でも5行めのif文が真になることは無いので常にret = 2になります。
$ cat -n b.c 1 int 2 b(unsigned int x) 3 { 4 int ret; 5 if (x < 0) { 6 ret = 1; 7 } else { 8 ret = 2; 9 } 10 return ret; 11 } 12
試したのはUbuntu 10.04でapt-getでインストールしたgccです。
$ gcc -v Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
まず普通にコンパイル。
$ gcc -c b.c $
何もwarningがでません。次に -Wall をつけてみます。
$ gcc -Wall -c b.c
$
おや?これでもでません。
$ gcc -W -c b.c
b.c: In function ‘b’:
b.c:5: warning: comparison of unsigned expression < 0 is always false
$
やっとでました。
オプション -Wall で全てのwarningが有効になると勘違いしていました。-Wextra とすると-Wallよりもたくさんのwarningが出ます。-W は -Wextraの古い書き方です。
つまり、warningの出る種類の多さに関しては
-Wextra = -W > -Wall
参考までに、warningを止めるには -w (小文字のw)
今回のものだけ個別に有効にするには以下のようにします。
$ gcc -Wtype-limits -c b.c
b.c: In function ‘b’:
b.c:5: warning: comparison of unsigned expression < 0 is always false
$
gccのマニュアル
gccのマニュアルから関連するところを抜粋しておきます。
-Wall This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. -Wall turns on the following warning flags: -Waddress -Warray-bounds (only with -O2) -Wc++0x-compat -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmain (only for C/ObjC and unless -ffreestanding) -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreorder -Wreturn-type -Wsequence-point -Wsign-compare (only in C++) -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wvolatile-register-var Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra but many of them must be enabled individually. -Wextra This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.) -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) The option -Wextra also prints warning messages for 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 which has been declared `register'. * (C++ only) Taking the address of a variable which has been declared `register'. * (C++ only) A base class is not initialized in a derived class' copy constructor.