2

次のコードを検討してください。

$ cat o.c 
#include <stdio.h>
#include <limits.h>

int absolute(int i) {
  int j = i < 0 ? -i : i;
  if (j<0)      /* This is line 6 */
    return 0;
  return j;
}

int main() {
  int i = 1;
  printf("%d %d\n", i, absolute(i));
  return 0;
}

でコンパイルすると-O2-Wstrict-overflow警告が生成されます。

$ gcc -O2 -Wall -Wextra -Wstrict-overflow o.c 
o.c: In function ‘absolute’:
o.c:6:6: warning: assuming signed overflow does not occur when simplifying comparison of absolute value and zero [-Wstrict-overflow]

ここで、上記のコードと機能的に同等と思われる次のコードを検討してください。

$ cat p.c 
#include <stdio.h>
#include <limits.h>

int main() {
  int i = 1;
  int j = i < 0 ? -i : i;
  if (j<0) // Changing i to INT_MIN above and changing (j<0) to (j>INT_MAX)
           // doesn't change the behavior
    j=0;
  printf("%d %d\n", i, j);
  return 0;
}

これを同じオプションでコンパイルしても、警告は発生しません。

$ gcc -O2 -Wall -Wextra -Wstrict-overflow p.c 
$

2 番目のコードでコメントされているように、割り当てを to に変更しi=INT_MIN;、条件を toに変更し(j>INT_MAX)ても、警告は表示されません。

Ubuntu で gcc 4.7.2 を使用しています。

$ gcc --version
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

2つのケースの違いを理解できません。最適化と関係がありますか、それとも gcc がここで正しく動作していませんか?

4

2 に答える 2

8
于 2013-07-22T10:57:05.237 に答える
2

最初のプログラムでは、最適化プログラムは、絶対値の符号がコンパイル時に不明な可変引数でチェックされることを認識します。

2 番目のプログラムでは、 の値iが既知であり、 と の結果はj、最初のプログラムで使用されたような最適化を行う前にj < 0、コンパイル時に計算されます。

これを確信させる良い方法はi、2 番目のプログラムの の値を、実行時にのみ認識される値に変更することです。

int i = 1 + printf(""); // 1 if no error, cannot be deduced
                        // at compile time
int j = i < 0 ? -i : i;
if (j<0) 

でコンパイルすると、最初のプログラムと同じ警告が表示され-O2 -Wstrict-overflowます。

于 2013-07-22T11:09:04.813 に答える