我有一个声明为的函数:
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
,并且该转换的结果是明确定义的。这是该语言的一个特性,除非您的编译器碰巧给您提供了这样做的方法,否则您无法将其关闭——而且我不知道有哪个编译器可以关闭它。
就您的功能而言,这两个调用:
foo(-1); /* -1 is converted to unsigned int, to the value UINT_MAX */
foo(UINT_MAX);
无法区分。这不是唯一的情况。任何负值int
都将转换为有效值unsigned
。
如果认为非常大的值对 无效foo()
,那么您可以检查参数值是否在某个“合理”范围内——但定义什么是“合理”并不总是那么容易。
foo
正如 wich 的回答所暗示的,您可以添加一个带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
type int
,所以调用foo(1)
也会抛出异常。一些其他有效的调用,例如foo(1.0)
,变得模棱两可。
如果您可以替换foo(1)
为foo(1U)
,其中1U
是类型的常量unsigned int
,那么这可以工作。
我不是 C++ 专家,但是...
您只有固定数量的位(通常是 32 或 64)来表示一个整数。如果你知道你永远不会有一个小于零的整数,你可以使用所有这些位并存储一个更大的数字。如果您的数字可能小于零,则编译器必须为符号保留一点。
它比这更复杂一些 - 请参阅Wikipedia 上关于 2 的补码的文章。
长话短说,在 foo 内部,如果您看到 x“非常非常大”,您可能已经传递了一个负数。
检查您的编译器文档以了解 int 与 uint 的大小。
您可能希望将您的参数更改为常规整数void foo(int x)
,或者只是放松地知道您当前的设置 x 永远不会小于零。
这是一个可能的解决方案:
void foo(unsigned int x)
{
unsigned int last_bit_one = 1 << 31;
if ( (x & last_bit_one) != 0) // check if the last bit of x is 1
std::cout << "NEGATIVE NUMBER" << std::endl;
else
std::cout << "do something" << std::endl;
}
当然,我们需要假设您输入的无符号数小于 2147483648。