2012-07-18 118 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