8

次のようなファイル test.cpp があります。

void f(const int n) {
  unsigned char *a=new unsigned char[n];
  delete[] a;
}

int main() {
  f(4);
  return 0;
}

-Wsign-conversionフラグを指定して 64 ビット GCC でコンパイルすると、次の警告が表示されます。

test.cpp:2:39: warning: conversion to ‘long unsigned int’ from ‘const int’ may change the sign of the result [-Wsign-conversion]

(2 行目はnewが呼び出される行です)。配列の割り当てについて GCC がこの警告を表示するのは奇妙に思えますが、次のことはさらに奇妙です。

  1. 問題のある行を に置き換えてunsigned char *a=new unsigned char[(long unsigned int)n];も、警告は取り除かれませんstatic_cast<long unsigned int>()
  2. fが署名void f(T n)で定義されている場合、警告は生成されませんT

    1. 任意のサイズの非定数、符号付きまたは符号なし整数型、または
    2. 符号付き 64 ビット整数型。

    ただしT、const 符号付き整数型が 64 ビットより小さい場合は、警告が生成されます。

私は64ビット(Linux)マシンを使用していることを念頭に置いてn、この場合、符号変換の警告がconstnessとサイズを気にするのはなぜですか?また、型キャストで問題が解決しないのはなぜですか?

注 1: 別のコンパイラでこれをテストしたかったのですが、Comeau サイトがダウンしており、他のコンパイラにアクセスできないため、これが標準準拠の動作なのか GCC のバグなのかわかりません。

注2:test.cppは、私が持っている「実際の」C++ファイルの問題の最小限の例であり、警告を取り除くための最良の方法は、問題のある行を次のように囲むことでした。

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
// ...
#pragma GCC diagnostic pop
4

8 に答える 8

0

それはあなたのために変換しますが、それが行っている変換がそれが変更している値の符号を変更することを警告します。配列の境界演算子にintを渡した場合、通常は符号の値を変更します。このように警告することはありません

あなたが持っている変換フラグを回転させてみて、それがまだこれを行うかどうかを確認してください

于 2013-05-03T03:42:52.577 に答える
0

これは、整数リテラルの処理方法に関係していると思います。

int myArray[10];

数字の 10 は符号付き整数に変換されますが、明らかな理由から、コンパイラはそれについて不平を言うべきではありません。したがって、符号付き整数の型チェックで例外が発生すると思います。const int を使用すると、gcc はこれを整数例外が適用されない別の型と見なすため、警告が表示されます。

于 2013-06-15T08:45:51.763 に答える