簡體   English   中英

是&,|,^按位運算符還是邏輯運算符?

[英]Are the &, |, ^ bitwise operators or logical operators?

首先,我了解到&| ^是按位運算符,現在有人用&&||它們稱為邏輯運算符。 ,我完全感到困惑-同一操作員有兩個名字嗎? 已經有邏輯運算符&&|| ,為什么要使用&| ^

Java運算符&| ^分別是按位運算符或邏輯運算符...取決於操作數的類型。 如果操作數是整數,則運算符是按位的。 如果它們是布爾值,則運算符是邏輯的。

這不僅是我說的。 JLS也以這種方式描述了這些運算符。 參見JLS 15.22

(這就像+一樣,表示加法運算或字符串串聯...取決於操作數的類型。或者就像“玫瑰”表示花朵或淋浴附件。或“貓”表示毛茸茸的動物或動物。 UNIX命令。單詞在不同的上下文中具有不同的含義。編程語言中使用的符號也是如此。)


已經有邏輯運算符&&|| ,為什么使用&| ^

就前兩個而言,這是因為運算符在何時/是否對運算數求值方面具有不同的語義。 在不同情況下需要兩種不同的語義。 例如

    boolean res = str != null && str.isEmpty();

    boolean res = foo() & bar();  // ... if I >>need<< to call both methods.

^運算符沒有短路等效項,因為擁有一個短路符根本沒有意義。

擁有語言參考是一回事,正確地解釋它是另一回事。

我們需要正確地解釋事物。

即使Java記錄了&既是按位又是邏輯的,我們仍可以提出這樣的論據,即&自從遠古時代以來就並沒有喪失其邏輯操作者的魔力,因為C。也就是說, &首先是一個固有的邏輯運算符(盡管那是一個非短路的)

&詞法上+邏輯上分析為邏輯運算。

為了證明這一點,從C到現在,這兩行的行為都相同(Java,C#,PHP等)

if (a == 1 && b)

if (a == 1 & b)

也就是說,編譯器將這些解釋為:

if ( (a == 1) && (b) )

if ( (a == 1) & (b) )

即使變量ab都是整數。 這個...

if (a == 1 & b)

...仍然會解釋為:

if ( (a == 1) & (b) )

因此,這將在不便於整數/布爾對偶的語言(例如Java和C#)上產生編譯錯誤。

if (a == 1 & b)

實際上,在上面的編譯錯誤中,我們甚至可以提出一個論點,即&沒有失去其邏輯(非短路)操作mojo,並且可以得出結論,Java繼承了C的傳統,使得&仍然是邏輯操作。 因此,我們可以說是另一回事了,即可以將&用作按位運算(通過應用括號):

if ( a == (1 & b) )

因此,在另一個並行世界中,我們可能會問,如何使&表達式成為位掩碼操作。

如何進行以下編譯,我在JLS中讀取了&是按位操作。 a和b都是整數,但是我無法理解為什么以下按位運算是Java中的編譯錯誤:

如果(a == 1&b)

還是這樣的問題:

為什么下面的代碼不能編譯,我在JLS中讀到&是兩個操作數均為整數時的按位運算。 a和b都是整數,但是我無法理解為什么以下按位運算是Java中的編譯錯誤:

如果(a == 1&b)

實際上,如果已經存在與上述問題類似的現有的stackoverflow問題,我會對此感到驚訝,這些問題詢問了如何在Java中執行該掩蓋習慣。

為了使該語言的邏輯運算解釋按位進行,我們必須這樣做(在所有語言,C,Java,C#,PHP等上):

if ( a == (1 & b) )

因此,回答這個問題並不是因為JLS定義了這種方式,而是因為Java(以及其他受C啟發的語言)的&運算符出於所有意圖,並且仍然是邏輯運算符,它保留了C的語法和語義。 這是因為C語言的方式 ,自遠古以來,因為之前我甚至出生。

事情並非偶然發生,JLS 15.22並非偶然發生,它有着悠久的歷史。

在另一個並行世界中,沒有將&&引入語言,我們仍將使用&進行邏輯運算,今天甚至可能會問一個問題:

是真的,我們可以使用邏輯運算符&進行按位運算嗎?

& 不在乎其操作數是否為整數,是否為布爾值。 仍然是一個邏輯運算符 ,一個非短路運算符 實際上,迫使它成為Java(甚至C語言)中按位運算符的唯一方法是在其周圍加上括號。

if ( a == (1 & b) )

考慮一下,如果&&沒有引入C語言(以及任何復制其語法和語義的語言),那么現在任何人都可以問:

如何使用&進行按位運算?

總而言之,Java &本質上是一個邏輯運算符(非短路運算符),它並不關心其操作數,即使兩個操作數都將照常進行操作(應用邏輯運算)是整數(例如,掩碼成語)。 您只能通過應用括號將其強制變為按位運算。 Java延續了C的傳統

如果Java的&確實是按位運算,並且其操作數(下面的示例代碼中的整數1和整數變量b )都是整數,則應編譯為:

 int b = 7;
 int a = 1;

 if (a == 1 & b) ...

它們( &| )很久以前就用於兩個目的,即邏輯運算符和按位運算符。 如果您要檢查新生兒C(語言是Java的后繼方式), &| 被用作邏輯運算符。

但是,由於在同一條語句中將按位運算與邏輯運算區別開來非常令人困惑,因此它提示Dennis Ritchie為邏輯運算符創建一個單獨的運算符( &&|| )。

在此處檢查新生兒C部分: http : //cm.bell-labs.com/who/dmr/chist.html

您仍然可以將按位運算符用作邏輯運算符 ,其保留的運算符優先級就是證明。 讀出按位運算符的前世歷史,作為新生兒C上的邏輯運算符

關於證據,我在博客文章中比較了邏輯運算符和按位運算符。 不言而喻的是,如果您嘗試在實際程序中進行對比,那么所謂的按位運算符仍然是邏輯運算符: http : //www.anicehumble.com/2012/05/operator-precedence-101.html

我還回答了一個與您有關C中邏輯運算符的意義是什么的問題

因此,按位運算符也是邏輯運算符,盡管短路邏輯運算符的非短路版本也是如此。


關於

已經有邏輯運算符&&,||,那么為什么要使用&,|,^?

XOR很容易回答,就像一個單選按鈕,只允許一個,下面的代碼返回false。 對於下面人為設計的代碼示例表示歉意,認為同時喝啤酒和牛奶都是不好的信念已經揭穿了 ;-)

String areYouDiabetic = "Yes";
String areYouEatingCarbohydrate = "Yes";


boolean isAllowed = areYouDiabetic == "Yes" ^ areYouEatingCarbohydrate == "Yes";

System.out.println("Allowed: " + isAllowed);

沒有等效於XOR按位運算符的短路,因為需要對表達式的兩端進行求值。

關於為什么需要使用&| 按位運算符作為邏輯運算符,坦率地說,您將很難找到使用按位運算符(也稱為非短路邏輯運算符)作為邏輯運算符的需要。 如果您想獲得一些副作用並使代碼緊湊(主觀的),則邏輯操作可以是非短路的(通過使用按位運算符,也稱為非短路邏輯運算符),例如:

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-prompt

}

上面的代碼可以重寫為以下代碼(刪除括號),但其解釋仍與前面的代碼完全相同。

while ( !password.isValid() & attempts++ < MAX_ATTEMPTS ) {

    // re-prompt

}

除去括號后,它仍然產生與括號中相同的解釋,可以使&邏輯運算符痕跡更加明顯。 為了冒聽起來多余的風險,但我必須強調,未加括號的表達式不能解釋為:

while ( ( !password.isValid() & attempts++ ) < MAX_ATTEMPTS ) {

    // re-prompt

}

綜上所述,使用&運算符(通常更廣為人知的是按位運算符,但是實際上兼具按位和邏輯(非短路))來實現副作用的非短路邏輯很聰明(主觀),但不鼓勵這樣做,它只是節省一行代碼以換取可讀性。

源自以下示例: 存在非短路邏輯運算符的原因

Java類型字節已簽名,這對於按位運算符可能是個問題。 當負數字節擴展為int或long時,將符號位復制到所有更高的位以保留解釋后的值。 例如:

byte b1=(byte)0xFB; // that is -5
byte b2=2;
int i = b1 | b2<<8;
System.out.println((int)b1); // This prints -5
System.out.println(i);       // This prints -5

原因:(int)b1內部為0xFFFB,b2 << 8為0x0200,所以我將為0xFFFB

解:

int i = (b1 & 0xFF) | (b2<<8 & 0xFF00);
System.out.println(i); // This prints 763 which is 0x2FB

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM