简体   繁体   English

一元减号运算符如何在C ++中使用布尔值?

[英]How does the unary minus operator work on booleans in C++?

I am currently converting some OpenCV code from C++ to Java. 我目前正在将一些OpenCV代码从C ++转换为Java。 I can't use JavaCV, as we need the conversion in native Java, not a JNA. 我不能使用JavaCV,因为我们需要在本机Java中进行转换,而不是JNA。 At one point in the code, I get the following assignment: 在代码中的某一点,我得到以下任务:

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

Where dst is uchar* , kHit and kForeground are int s. 其中dstuchar*kHitkForegroundint

I've been unable to find anything about how this works, and Java will not recognize it as an operation. 我一直无法找到有关其工作原理的任何信息,Java也不会将其识别为操作。 There is an operation on these two variables at another point in the code, and it stores one of two values: 255 or 0. 这两个变量在代码的另一个点上有一个操作,它存储两个值中的一个:255或0。

The code in question comes from opencv/video/src/bgfg_gaussmix.cpp . 有问题的代码来自opencv/video/src/bgfg_gaussmix.cpp

In C++ a boolean expression produces one of two values - 0 or 1 . 在C ++中,布尔表达式生成两个值中的一个 - 01 When you apply the unary minus - to the result, you get 0 or -1 . 当你将一元减去-应用于结果时,你会得到0-1 When you re-interpret -1 as uchar , you get 255 . 当您将-1重新解释为uchar ,您将获得255

You can convert this expression to Java with a conditional: 您可以使用条件将此表达式转换为Java:

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

Because of branching, it is not going to be as fast as the original one. 由于分支,它不会像原始分支一样快。 There's little you can do about the speed of it, however, as Java lacks abilities to re-interpret boolean values as numerics. 然而,由于Java缺乏将布尔值重新解释为数值的能力,因此关于它的速度几乎无法做到。

kHit >= kForeground returns either true or false , which in C++ sort of means 1 or 0 . kHit >= kForeground返回truefalse ,这在C ++中表示10 The minus in front transforms this to -1 or 0 . 前面的减号将其转换为-10 The cast to uchar ( (uchar) ) returns 0 for 0 and wraps to 255 for the negative -1 . uchar(uchar) )的(uchar)0 ,返回0 ,负-1返回255

Following Konrad's comment, I'm also skeptical this is well defined. 在康拉德的评论之后,我也怀疑这个定义是否明确。 It is well defined, but it's still an awful piece of code in terms of readability. 它定义明确,但就可读性而言,它仍然是一段糟糕的代码。 :) :)

What it basically does is following: 它基本上做的是:

kHit >= kForeground

is an expression of type bool 是bool类型的表达式

-(kHit >= kForeground)

converts this bool into an int (based on true==1 and false==0 ) and negates it, which results in true==-1 and false==0 . 将此bool转换为int(基于true==1false==0 )并将其否定,从而得到true==-1false==0

This is then converted into a uchar , which results in -1==255 and 0==0 . 然后将其转换为uchar ,结果为-1==2550==0

It has to be noted that though seeming as using the underlying implementation details of the numbers, all those conversions are guaranteed by the C++ and C standards, as negative unsigned numbers are specified to behave according to twos-complement. 必须注意的是,虽然看起来使用数字的底层实现细节,但所有这些转换都由C ++和C标准保证,因为负无符号数被指定为根据二进制补码运行。

But if Java doesn't support this, you can always replace it by a conditional assignment: 但是,如果Java不支持这一点,您始终可以通过条件赋值替换它:

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

The expression (kHit >= kForeground) yields a boolean that has value true or false . 表达式(kHit >= kForeground)产生一个值为truefalse的布尔值。 When the unary - is applied, the bool gets promoted to an int , and the conversion yields 1 for true or 0 for false . 当应用一元-时, bool被提升为int ,转换为1表示true0表示false After the promotion, the sign is changed into -1 or 0 and then it is converted to uchar by the outer cast. 升级后,符号将更改为-10 ,然后由外部转换转换为uchar

Note that the important bit of information is that the unary operator- is not applied to a boolean, but the boolean is converted to int and it is then applied. 请注意,重要的信息是一元运算operator-不应用于布尔值,但布尔值转换为int ,然后应用它。 That can be tested with a bit of template magic: 这可以通过一些模板魔术来测试:

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);
}

The f template tests the type of the passed argument against int and bool by using the same_type templates above (trivial enough to understand). f模板使用上面的same_type模板测试传递的参数对intbool的类型(很容易理解)。 If we call the f template with -true as argument type deduction will set T to be the type of the expression -true . 如果我们使用-true调用f模板作为参数类型,则将T设置为表达式-true的类型。 If you run the program, you will see that it prints Is int? true\\nIs bool? false 如果你运行程序,你会看到它打印出来Is int? true\\nIs bool? false Is int? true\\nIs bool? false Is int? true\\nIs bool? false . Is int? true\\nIs bool? false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM