私は次のように宣言された関数を持っています:
void foo(unsigned int x)
foo()が負の数を受け取っていないことを確認するにはどうすればよいですか?foo(-1)を呼び出すと例外がスローされますが、もちろんxは自動的に符号なしに変換されるため、次のようにその陽性を確認することはできません。
if not(x>=0){ do_something();};
または同様のチェック。
これを行う良い方法はありませんが、いくつかのトリックで行うことができます。
1) 未定義のより良い一致を宣言します。
void foo(unsigned int x) {
//do something
}
void foo(int x);
2) typeid を使用して型を決定します。
引数を取るように関数を定義したためunsigned int
、負の値を受け取ることはできません。
引数を指定して呼び出すとint
、その値は暗黙的に から に変換されint
、unsigned int
その変換の結果は明確に定義されます。これは言語の機能であり、コンパイラがたまたまそうする方法を提供しない限り、それをオフにすることはできません-そして、私はそうするコンパイラを知りません.
関数に関する限り、これら 2 つの呼び出しは次のとおりです。
foo(-1); /* -1 is converted to unsigned int, to the value UINT_MAX */
foo(UINT_MAX);
見分けがつきません。それだけではありません。負の値は有効な値に変換されます。int
unsigned
非常に大きな値が に対して無効であると見なされる場合foo()
、パラメータ値が「妥当な」範囲内にあるかどうかを確認できますが、「妥当な」範囲を定義することは必ずしも容易ではありません。
ウィッチの答えが示唆するように、引数foo
を取るオーバーロードされたバージョンを追加できます。そして、例外をスローしint
たいと言ったので、オーバーロードされたものにそれをさせることができます:foo(-1)
foo()
#include <iostream>
class Wrong_Type {
public:
Wrong_Type(){}
};
void foo(unsigned n) {
std::cout << "In foo, unsigned n = " << n << "\n";
}
void foo(int n) {
std::cout << "In foo, int n = " << n << "\n";
throw Wrong_Type();
}
int main() {
try {
foo(-1);
}
catch (Wrong_Type) {
std::cout << "Caught Wrong_Type exception\n";
}
}
これを実行すると、出力は次のようになります。
In foo, int n = -1
Caught Wrong_Type exception
ただし、これは理想的なソリューションではありません。値ではなく、引数の型に基づいて例外をスローするためです。1
とは両方とも-1
typeint
であるため、呼び出しfoo(1)
も例外をスローします。また、 などの他の有効な呼び出しもfoo(1.0)
あいまいになります。
foo(1)
で置き換えることができればfoo(1U)
、1U
は type の定数でありunsigned int
、これはうまくいく可能性があります。
私は C++ の専門家ではありませんが、...
整数を表すには固定数のビット (通常は 32 または 64) しかありません。ゼロ未満の整数が決してないことがわかっている場合は、それらのビットをすべて使用して、はるかに大きな数値を格納できます。数値がゼロ未満である可能性がある場合、コンパイラは符号用にビットを予約する必要があります。
それよりも少し複雑になります - 2 の補数に関するウィキペディアの記事を参照してください。
簡単に言うと、foo の中で x が「本当に大きい」とわかったら、負の数が渡された可能性があります。
int と uint のサイズについては、コンパイラのドキュメントを確認してください。
おそらく、param を通常の整数に変更するかvoid foo(int x)
、現在の設定では x が 0 未満になることは決してないことを知ってリラックスする必要があります。