Яка різниця між | та || чи операторів?


300

Я завжди використовував ||(дві труби) у виразах АБО, як у C #, так і в PHP. Іноді я бачу єдину трубу використовується: |. Яка різниця між цими двома звичаями? Чи є якісь застереження при використанні одного над іншим або вони взаємозамінні?

Відповіді:


488

Так само, як &і &&оператор, подвійний Оператор є оператором "короткого замикання".

Наприклад:

if(condition1 || condition2 || condition3)

Якщо умова1 вірна, умови 2 та 3 НЕ перевіряються.

if(condition1 | condition2 | condition3)

Це дозволить перевірити умови 2 і 3, навіть якщо 1 вже відповідає дійсності. Оскільки ваші умови можуть бути досить дорогими функціями, ви можете отримати гарне підвищення продуктивності, використовуючи їх.

Є один великий застереження, NullReferences або подібні проблеми. Наприклад:

if(class != null && class.someVar < 20)

Якщо клас недійсний, виписка if припиниться після class != nullfalse. Якщо ви тільки використовуєте &, він спробує перевірити, class.someVarі ви отримаєте хороший NullReferenceException. З Or-Operator це може бути не стільки пастки, оскільки навряд чи ви запускаєте щось погане, але це потрібно пам’ятати.

Ніхто ніколи не використовує сингл &або |операторів, якщо ви не маєте дизайну, де кожна умова є функцією, яку потрібно виконати. Звучить, як дизайнерський запах, але іноді (рідко) це чистий спосіб робити речі. &Оператор не "запустити ці 3 функції, і якщо один з них повертає брехня, виконати ще блок», в той час як |це «тільки запустити ще блок , якщо жоден повернення помилковим» - може бути корисним, але , як сказав, часто це дизайн запах.

Однак існує друге використання оператора |та &оператора: Побітові операції .


9
Так, я не повірив, поки не створив консольний додаток - але добрий пане! Чому б вони дали вам мотузку, щоб повіситись! Я ненавидів це про VB.NET - ключові слова OrElse та AndAlso!
Jarrod Dixon

24
Навчити людей користуватися &і |як умовні оператори - це хак, і вони змусять себе мати проблеми, якщо вони коли-небудь потребують використання C / C ++: 1 && 2це правда, а 1 & 2неправда.
BlueRaja - Danny Pflughoeft

47
Це не хак, це офіційно визначено для C # у Розділі 7.10.3 Булеві логічні оператори: "Результат x | y є істинним, якщо x або y є істинним. Інакше результат хибний." Також дивіться Розділ 7.11 Умовно-логічні оператори: "Операція x || y відповідає операції x | y, за винятком того, що y оцінюється лише в тому випадку, якщо x помилково". що далі "легалізується" | як умовний оператор. І люди, які будуть використовувати C / C ++, у будь-якому випадку опиняться у біді, якщо вони просто сліпо вважають, що матеріал працює однаково. Як сказано: Використання | у викладі if, якщо це дизайнерський запах, але цілком законна операція.
Майкл Стум

9
Я ніколи не казав, що це не законно, просто що це хакер, який він є (ви використовуєте &для передачі сенсу, відмінного від того, що це майже завжди означає: побіт-і) .
BlueRaja - Danny Pflughoeft

15
@ BlueRaja-DannyPflughoeft Виклик документально закріпленої функції взлома, коли в документації говориться, що вона мала бути використана, - це як сказати з використанням заяви перемикання "злом на інших". Її інструмент у коробці інструментів, можливо, рідко використовується спеціальний інструмент, але не менш інструмент.
Gent

80

|| є логічним оператором АБО. Здається, ви в основному знаєте, що це таке. Він використовується в умовних висловлюваннях, таких як if, while і т.д.

condition1 || condition2

Оцінюється як істинне, якщо будь-яка умова1 АБО умова2 є істинною.

| - оператор побітових АБО Він використовується для роботи на двох номерах. Ви дивитеся на кожен біт кожного числа окремо, і якщо один з бітів дорівнює 1 принаймні одному з чисел, то отриманий біт також буде 1. Ось кілька прикладів:

A = 01010101
B = 10101010
A | B = 11111111

A = 00000001
B = 00010000
A | B = 00010001

A = 10001011
B = 00101100

A | B = 10101111

Сподіваємось, це має сенс.

Отже, щоб відповісти на два останні запитання, я б не сказав, що є будь-які застереження, окрім "знайте різницю між двома операторами". Вони не взаємозамінні, оскільки роблять дві абсолютно різні речі.


Це допомогло мені зрозуміти, як хтось використовував оператор бітового АБО для об'єднання фільтрів у драйвері Mongodb C #. gist.github.com/a3dho3yn/…
Донні В.

30

Один - "побитовий або".

10011b | 01000b => 11011b

Інша - це логіка або.

true або false => правда


2
|може використовуватися і на boolтипах, без короткого замикання.
juharr

14

Хороше питання. Ці два оператори працюють однаково у PHP та C #.

|є побітним АБО. Він порівняє два значення за їх бітами. Напр. 1101 | 0010 = 1111. Це надзвичайно корисно при використанні бітових параметрів. Наприклад, читання = 01 (0X01) запис = 10 (0X02) читання-запис = 11 (0X03). Один корисний приклад - відкриття файлів. Простим прикладом може бути:

File.Open(FileAccess.Read | FileAccess.Write);  //Gives read/write access to the file

||є логічним АБО. Саме так більшість людей думає про АБО і порівнює два значення, виходячи зі своєї правди. Наприклад, я йду в магазин або піду в торговий центр. Це найчастіше використовується в коді. Наприклад:

if(Name == "Admin" || Name == "Developer") { //allow access } //checks if name equals Admin OR Name equals Developer

Ресурс PHP: http://us3.php.net/language.operators.bitwise

C # Ресурси: http://msdn.microsoft.com/en-us/library/kxszd0kx(VS.71).aspx

http://msdn.microsoft.com/en-us/library/6373h346(VS.71).aspx


4
FWIW, технічно, в C # |є логічним або при застосуванні до булевих . Як вказано у вашій довідковій справі. На практиці кінцевий результат такий самий, як якщо б це був побітовий оператор, тому що побітові значення trueта falseтакі, що порозрядне або їх значення дає такий же результат, як і логічний чи дійсний. Тобто (int)(bool1 | bool2)== ((int)bool1) | ((int)bool2).
ToolmakerSteve

4

Простий приклад у Java

public class Driver {

  static int x;
  static int y;

public static void main(String[] args) 
throws Exception {

System.out.println("using double pipe");
    if(setX() || setY())
        {System.out.println("x = "+x);
        System.out.println("y = "+y);
        }



System.out.println("using single pipe");
if(setX() | setY())
    {System.out.println("x = "+x);
    System.out.println("y = "+y);
    }

}

 static boolean setX(){
      x=5;
     return true;
  }
 static boolean setY(){
      y=5;
      return true;
  }
}

вихід:

using double pipe
x = 5
y = 0
using single pipe
x = 5
y = 5

2
Чому б ви навели приклад java для питання, яке навіть не згадує про java?
juharr

4

& - (Умова 1 та Умова 2): перевіряє обидва випадки, навіть якщо перший з них є помилковим

&& - (Умова 1 та & Умова 2): не намагайтеся перевіряти другий випадок, якщо випадок 1 неправдивий

&& - оператор змусить ваш код працювати швидше, професійно і його рідко використовують

| - (Умова 1 | Умова 2): перевіряє обидва випадки, навіть якщо випадок 1 є істинним

|| - (Умова 1 || Умова 2): не турбуйтеся перевіряти другий випадок, якщо перший є істинним

|| - оператор змусить ваш код працювати швидше, професійно | використовується рідко


2
rarely used? Все залежить від того, що ви хочете або потрібно зробити.
Емаборса

1
Чудово! Короткий і солодкий, я б видалив "| рідко використовується" і "& рідко використовується", тому що, як сказав Емаборса, це дійсно залежить від того, що ви хочете або потрібно зробити.
Янник

0

Одинарна труба, |, є одним з розрядних операторів.

З Вікіпедії:

У сімействі мов програмування на C оператором бітового АБО є "|" (труба). Знову ж таки, цього оператора не слід плутати зі своїм булевим "логічним" або "аналогом", який трактує його операнди як булеві значення та пишеться "||" (дві труби).


0

За своїм математичним визначенням АБО та І є двійковими операторами; вони перевіряють умови LHS та RHS незалежно, як | і &.

|| та && змінювати властивості операторів OR і AND, зупиняючи їх, коли умова LHS не виконується.


-1

| Оператор виконує побіт АБО двох своїх операндів (тобто обидві сторони повинні оцінювати значення false, щоб повернути помилкові), тоді як || Оператор оцінить другого оператора лише в тому випадку, якщо це потрібно.

http://msdn.microsoft.com/en-us/library/kxszd0kx(VS.71).aspx

http://msdn.microsoft.com/en-us/library/6373h346(VS.71).aspx


Якби ви насправді читали ці статті, ви б побачили, що вони посилаються на побітові оператори
johnc

Це не те, що побито означає.
juharr

-1

Сінг-труба "|" є "побітним" або і має використовуватися лише тоді, коли ви знаєте, що робите. Подвійна труба "||" є логічним або, і може використовуватися в логічних висловлюваннях, як "x == 0 || x == 1".

Ось приклад того, що розрядне чи дійсне: якщо a = 0101 і b = 0011, то a | b = 0111. Якщо ви маєте справу з логічною системою, яка розглядає будь-який ненульовий показник як істинний, то побітове або поступить так само, як і логічне або, але це аналог (порозрядно і "&") НЕ буде. Також розрядне або не виконує оцінку короткого замикання.


'|' також можна використовувати на boolтипи без короткого замикання.
juharr

-2

Одинарна труба (|) є оператором побітових АБО .

Дві труби (||) є логічним оператором АБО.

Вони не взаємозамінні.


1
Якщо ви ігноруєте побітну операцію, подвійна труба - це лінива оцінка, а одна трубка - жадібна, в межах логічного оператора.
Олексій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.