三元演算子とのポインター変換の問題
質問
私は、三元オペレーターにいくつかの驚くべき制限があることを知っていますが、私はこれが私のためにコンパイルできないことに少し困惑しました:
void foo(bool b)
{
int* ptr = ((b) ? NULL : NULL);
}
明らかに、それは問題を示すために必要な最低です。エラーは次のとおりです。
[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'
コンパイラは、100%以下のエンバカデロC ++ビルダー2010年であるため、コンパイラバグは不可能とはほど遠いものです...
注:私の意図についての混乱を避けるために修正されたパレンズ。
注2:そもそもこの構造に到着した方法について少し混乱したので、ここに言い訳があります。 a = b? c : d
, 、ここで、B、C、およびDはすべて複雑な式でした。それを絞り込むために、私は交換しました c
と d
と NULL
sかどうかを確認するため b
犯人でした。この時点で、すべてが手足で地獄に行きました。
解決
NULL
に拡張するマクロです 0
(またはの値を持つ何らかの積分定数式 0
, 、 例えば、 (1 - 1)
)。それ以外の場合は「特別」ではありません。
ゼロの値を持つ積分定数式は、ヌルポインター定数として使用可能です。これがその理由です int* ptr = 0;
許可されています。ただし、ここでは、表現はです b ? 0 : 0
;これは不可欠な定数式ではありません(b
一定ではありません);そのタイプはです int
, 、それは暗黙的に変換可能ではありません int*
回避策は、ポインタータイプが必要であることを明示的に指定することです。
int* const null_int_ptr = 0;
int* ptr = b ? null_int_ptr : null_int_ptr;
ただし、この例は少し不自然です。通常、条件付き演算子を使用する場合、少なくとも1つの引数は実際にはポインタータイプです(例: b ? ptr : 0
);オペランドの1つがポインタータイプである場合、 0
暗黙的に同じポインタータイプに変換されるため、条件式全体のタイプはポインタータイプではなく、 int
.
この「問題」を持つことができる唯一のケースは、条件演算子の2番目と3番目のオペランドとしてヌルポインター定数が使用される場合、かなり奇妙です。
他のヒント
あなたの問題はあなたのシステム上のものです NULL
と定義されています 0
これは、三元演算子のコンテキストではINTであると想定されています。もし、あんたが static_cast
オペランドの1つ int*
もう1つを自動宣伝する必要があります。
しかし、そもそもなぜそのような構成を使用しているのでしょうか?
NULL
タイプを持つと定義できます int
あるいは long
, 、したがって、三元演算子は同じタイプを持っています。ポインタータイプへの暗黙の変換はないため、コンパイラはエラーを生成します。ここでのゴッチャは、ゼロ(悪名高いヌルポインター定数)まで評価する定数整数発現から暗黙的な変換があることです。
ここでの可能な解決策は明示的なキャストです:
int* ptr = b ? (int*) NULL : NULL;