2012-07-18 114 views
5

我目前正在将一些OpenCV代码从C++转换为Java。我无法使用JavaCV,因为我们需要在本机Java中进行转换,而不是JNA。在代码中的一个点,我得到如下分配:单元减号运算符在C++中如何处理布尔运算符?

dst[x] = (uchar)(-(kHit >= kForeground)); 

哪里dstuchar*kHitkForegroundint秒。

我一直无法找到关于它如何工作的任何信息,Java不会将其识别为操作。这两个变量在代码中的另一点有一个操作,它存储两个值之一:255或0.

有问题的代码来自opencv/video/src/bgfg_gaussmix.cpp

回答

7

在C++中,一个布尔表达式产生两个值之一 - 01。当您将一元减号-应用于结果时,将得到0-1。当您将-1重新解释为uchar时,您将获得255

您可以将这个表达式转换成Java的一个条件:

dst[x] = (kHit >= kForeground) ? 255 : 0; 

因为分支,它不会是一样快的原单。但是,对于Java的速度,你无能为力,因为Java缺乏将布尔值重新解释为数字的能力。

+0

这是有道理的,而且我可以很容易地测试和发现我自己的东西。感谢您如此简洁地指出它。 – Wraith967 2012-07-18 15:18:33

+0

从技术上讲,布尔表达式产生'true'或'false',当提升为'int'时,将得到值'1'或'0'。 – 2012-07-18 15:28:41

6

kHit >= kForeground返回truefalse,其在C++中表示为10。前面的减号将其转换为-10。转换为uchar(uchar))将返回0代替0,并将255包装为负值-1

继康拉德的评论,我也怀疑这是明确的。它的定义很明确,但在可读性方面它仍然是一段糟糕的代码。 :)

+3

关于* some *编译器/机器。这个代码是不必要的不​​可移植的。 – 2012-07-18 14:48:01

+2

C++标准没有明确指定无符号类型的行为就像是二进制补码一样,所以这应该被很好地定义(因为true == 1和false == 0也被很好地定义)? – 2012-07-18 14:54:37

+0

@KonradRudolph:该标准指定:“bool类型的prvalue可以转换为int类型的prvalue,其中false为零,true为真。[conv.prom],并且'如果目标类型是无符号的,结果值是与源整数相等的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)'[conv.integral]。所以我认为这个代码实际上是在合规编译器中定义良好并且可移植的。 – 2012-07-18 15:22:10

1

什么它基本上是以下:

kHit >= kForeground 

是bool类型的表达式

-(kHit >= kForeground) 

此布尔转换成一个int(基于true==1false==0)和取消它,这将导致在true==-1false==0

然后将其转换为uchar,结果为-1==2550==0

需要注意的是,尽管看起来使用数字的底层实现细节,但所有这些转换都由C++和C标准保证,因为负无符号数指定为按照二进制补码行为。

但如果Java不支持此功能,您可以通过有条件分配总是替换它:

dst[x] = (kHit>=kForeground) ? 255 : 0; 
1

表达(kHit >= kForeground)产生具有价值truefalse一个布尔值。当应用一元-时,bool被提升为int,并且true0false的转换产量为1。升级后,标志变为-10,然后通过外部转换将其转换为uchar

请注意,重要的信息位是一元operator-未应用于布尔值,但布尔值转换为int,然后应用它。这可以用一点神奇的模板进行测试:

template <typename T, typename U> 
struct same_type { 
    static const bool value = false; 
}; 
template <typename T> 
struct same_type<T,T> { 
    static const bool value = true; 
}; 
template <typename T> 
void f(T value) { 
    std::cout << "Is int? " << std::boolalpha << same_type<T, int>::value << "\n"; 
    std::cout << "Is bool? " << same_type<T, bool>::value << "\n"; 
} 
int main() { 
    f(-true); 
} 

f模板通过使用上述same_type模板(足够的琐碎理解)测试对intbool传递的参数的类型。如果我们将f模板与-true作为参数类型推理,将T设置为表达式-true的类型。如果你运行该程序,你会看到它打印Is int? true\nIs bool? false

+0

很好的答案,但我认为你可以用两个基本的重载使整数转换的例子更加清晰。 'void f(int){cout <<“int \ n”; } void f(bool){cout <<“bool \ n”; } f(true); f(-true);' – 2012-07-18 15:36:47

+0

@LucTouraille:我猜,我刚刚在我的工具箱中找到了[锤](http://en.wikipedia.org/wiki/Law_of_the_instrument)(现在我认为它有一个更简单的方法:'template void print_type(T); print_type(-true);'('print_type'声明,未定义)会告诉你链接器消息中的类型 – 2012-07-18 16:01:10