1. ホーム
  2. C/C++ Programming

コンパイル時の警告をなくす(Warning)

2022-02-13 16:57:53

<スパン コンパイル時の警告をどう考えるか

コンパイラは、プログラムの中に疑わしいもの、問題がありそうなものを見つけると、警告メッセージを出します。警告メッセージは、プログラムに潜む大きなエラーを意味していることもあれば、問題がないことを意味していることもあります。警告に対処する適切な方法は、可能な限り警告をなくすことです。コンパイラが出す警告は、それぞれ注意深く分析して、本当に問題があるかどうかを確認する必要があります。本当に問題がない警告だけを取り去るべきです。

説明

コンパイル時の警告の種類は非常に多く、すべてを列挙することは不可能なので、ここでは代表的なものをいくつか紹介し、さらに文字通りの意味を追うだけですぐに見つけて修正できるものをいくつか紹介します。

タイプ1

表示する。 警告: 関数 `Example()' の暗黙の宣言です。

警告 (1) 関数 Example() が .c ファイルで呼び出されていますが、関数を宣言している対応する .h ファイルをインクルードしていません。

         (2) .c ファイルで関数本体を定義したが、.h ファイルで宣言していない可能性があります。

解決方法 (1) そのような関数を呼び出す .c ファイルの冒頭に extern Example() を追加すればよい。

         (2) この関数を呼び出す .c ファイルに、関数 Example() を宣言したヘッダファイルをインクルードすればよいのです。

         (3) 関数本体を.cファイルで定義し、.hで宣言しない場合、気にならなければそのまま関数宣言で.hファイルを生成してください。

同様の警告 警告: 前の暗黙の宣言との型の不一致

警告: 前の暗黙の宣言との型の不一致

警告: `Example()' の前の暗黙の宣言。

タイプ2

   表示する。 警告: 未使用の変数 `param' です。

   警告 どうやら、変数 'param' を定義しておきながら、まったく使っていないようです。

   解決方法 使用する必要がなければ、削除してください。

タイプ3

   表示する。 警告: 効果のないステートメントです。

   警告の理由 ファイル内でこのようなことをした場合に考えられること - #define MACROPRINT

             そして、その行のどこかで - #define MACROPRINT printf を定義しています。そして、いたるところで

MACROPRINT("HELLO") はエラーになりませんが、警告 "このステートメントは使用されていません" が表示されます。

   回避策:#define MACROPRINT を削除してください。

タイプ4

   表示する。 警告: int format, long int arg (arg 3)

   警告 このように printf("%s%d, szDebugString, ulGwId); ulGwId は unsigned long 型で、あなたが選んだ出力形式は "%d" (この形式は整数型 - int 用)です。

   解決方法 上記のケースのように、"%d" を "%ld" に変更し、パラメータの型を統一すればよいのです。

   同様の警告 警告:ポインタと整数の比較

タイプ5

   表示する。 警告:データ型の範囲が限定されているため、比較は常に0になる

   警告 unsigned int uParam; を定義したのに、if(uparam<0) の判定をしてしまった可能性があります。

unsigned intのデータは常に>=0なので、このような比較はデータ型によって範囲が制限されるため、警告が出ます。

 回避策 そのような判定を削除することができます。

タイプ6

   表示する。 警告: コントロールが非ボイド関数の末尾に到達しました。

警告の理由 このような警告が表示されるのは、あなたが以下のような文章を書いたからかもしれません。

符号なし長さ FuncA()

{ <未定義

if()

{return ulValue;}.

if()

{ return ulValue;}.

この場合、関数を終了する前に返すべき値がまったくありません。

   回避策 関数に戻り値がある場合、どんな場合でも関数に戻り値があることを確認してください。

   同様の警告 warning :`return' with no value, in function returning non-void

タイプ7

   表示する。 警告: 暗黙の定数変換におけるオーバーフロー

   警告: 暗黙の定数変換におけるオーバーフロー

#define RET_PRODUCTID 0x10000000

#define ERR_RET_GLOBAL RET_PRODUCTID+5000

#define RET_USER ERR_RET_GLOBAL+5000

#define USER_OK RET_USER+0

#define USER_FAIL RET_USER+1

このように定義して、short Func() {return USER_OK}に遭遇した場合、out-of-boundsであることを警告します。

   回避策 値の範囲を決定する。

タイプ8

   表示する。 警告: この関数では `ulParam' が初期化されていない状態で使用される可能性があります。

   警告 ulParam が式の正しい値であり、それ以前にパラメータを初期化していない場合。

              例:void Func()

                   { <未定義

                      ulong ulParam;

                      ulong ulRetCode。

                      if(...)

                      { <未定義

                         ulParam = ..................。

                      }

                      if(......)

                      { <未定義

                         ulParam = ..................。

}

ulRetCode = ulParam;

}

              この場合、どちらのif()も実行された時点では、ulParamは全く代入されていませんので、戻ってulRetCodeに値を代入する方が危険です。

   回避策 ただ、目を離さず、より注意することです。

タイプ9

   表示する。 警告: `free' の引数 1 を渡すと、キャストせずに整数からポインタを作成します。

   警告 free(a) としましたが、a は unsigned long であり、a の中にポインタの値を入れている可能性があります。

   解決方法 free(a)のとき、aを強制的にポインタ型にする必要があります。つまり、free((char*)a)とします。

   同様の警告 警告: 互換性のないポインタ型からの代入

警告: 互換性のないポインタ型からの初期化

警告: `AOS_MemCopy_X' の arg 2 を渡すと、キャストせずに整数からポインタを作成します。

10型

   表示する。 警告: `MY_DEBUG' は再定義されました。

警告: これは以前の定義の場所です。

   警告の理由 2つの警告が連続して発生する原因として、.cファイル内に2つの.hファイルが存在することが考えられます。

ファイルがあり、両方の .h ファイルで MY_DEBUG に関する宣言が行われています。

   回避策:この種のものは1つのファイルだけで宣言してください。

11型

   表示する。 警告:計算された値が使用されていません

   警告の理由:計算された値が使用されていません。例えば、このような場合。

char* p;

*p++;

これはpに全く影響を与えません。

   解決方法 どのような操作を行うかを正確に判断する。

12型

   表示する。 警告: `#ifdef' 引数は数字から始まります。

警告理由:#ifdef 0のようなエラー

   解決策 I think it's #if 0

13型

   表示する。 warning: 不明なエスケープシーケンス `R'

   警告理由: コンパイラは 'ⅳR' を認識しません。

   回避策:タイプミスです。'˶'˶。

タイプ14

   表示する。 警告:formatの引数が少なすぎる

   警告: 次のような操作を行った可能性があります: printf("%d%s",uParam);

   解決策:欲しいものを残し、要らないものを処分する。

タイプ15

    表示する。 警告: 'Func' は定義されているが使用されていません。

    警告 Func関数を定義したのに、全く使っていない。

解決策:不要なものは処分する。

16型

表示する。 警告: || 内の && を括弧で囲むことを推奨します。

警告理由: 誰かがこれを使った if( *p >= 'a' ) && ( *p <= 'z' ) || ( *p >= 'A' ) && ( *p <= 'Z' ) || ( *p >= '0' ) &&= ( *p <= '9' )

解答:if(( *p >= 'a' ) && ( *p <= 'z' )) || (( *p >= 'A' ) && ( *p <= 'Z' )) || (( *p >= '0' ) && ( *p <= '9' )) の方がいいのでしょう。