Чому "&&", а не "&"?


135

Чому &&краще &і ||краще |?

Я запитав когось, хто програмував роками, і його пояснення було:

Наприклад, в if (bool1 && bool2 && bool3) { /*DoSomething*/ }, bool1має бути істинним, щоб перевірити, bool2що має бути істинним, перш ніж переходити до bool3і т. Д. Якщо я використовував би один, &замість нього немає порядку для тесту, навіть якщо всі вони повинні бути правдивими перехід до наступного рядка, так чому це все одно має значення?

Примітка. Я хотів би зазначити, що я еквівалент програмування малюка, і це не серйозне або нагальне питання. Це більше питання розуміння того, чому все слід робити певним чином, а не іншим.


55
& і && | та || зовсім інші оператори
Felice Pollano

3
Позначено посиланнями, оскільки це стосується не лише C #
Джонатана Дікінсона,

12
Звернуто, тому що відповіді вже є специфічними для C #, а внутрішня робота може дещо відрізнятися в інших мовах, які мають загалом те саме поняття.
Даніель Гілгарт

8
@Felice: Вони різні, але навряд чи абсолютно різні. Насправді вони дуже схожі: x & yі x && yзавжди будуть оцінювати один і той же результат, якщо x і y - вирази булевого типу. Насправді єдиною різницею в цьому випадку, здається, є те, що у x & y, y завжди оцінюється.
Жорен

1
@slawekin: Я б запропонував прочитати відповіді. Деякі широко пишуть про відмінності в продуктивності. Відповідь, можливо, вас здивує.
Абель

Відповіді:


183

У більшості випадків, &&і ||краще &і |тому , що колишній закорочен, а це означає , що оцінка буде скасована , як тільки результат ясний.

Приклад:

if(CanExecute() && CanSave())
{
}

Якщо CanExecuteповертається false, повний вираз буде false, незалежно від значення повернення CanSave. Через це CanSaveне виконується.

Це дуже зручно за таких обставин:

string value;
if(dict.TryGetValue(key, out value) && value.Contains("test"))
{
    // Do Something
}

TryGetValueповертається, falseякщо наданий ключ не знайдений у словнику. Через коротке замикання характер &&, value.Contains("test")виконується лише тоді, коли TryGetValueповертається trueі при цьому valueнемає null. Якщо ви скористалися оператором bit bit AND& , ви отримаєте a, NullReferenceExceptionякщо ключ не знайдений у словнику, оскільки друга частина виразу виконується у будь-якому випадку.

Подібний, але простіший приклад цього - наступний код (як згадував TJHeuvel):

if(op != null && op.CanExecute())
{
    // Do Something
}

CanExecuteвиконується лише якщо opнемає null. Якщо opє null, перша частина виразу ( op != null) оцінює до, falseа оцінка решти ( op.CanExecute()) пропускається.

Крім цього, технічно, вони теж різні:
&&і ||можуть бути використані тільки boolтоді &і |може бути використаний на будь-який інтегрального типу ( bool, int, long, sbyte, ...), тому що вони є бітові оператори. &є побітовим оператором AND і |є побітним оператором АБО .

Якщо бути дуже точним, в C #, ці оператори ( &, |^]) називаються "логічні оператори" (див. Специфікацію C # , розділ 7.11). Існує кілька реалізацій цих операторів:

  1. Для цілих чисел ( int, uint, longі ulong, глава 7.11.1):
    Вони реалізуються , щоб обчислити результат побітового операндів і оператора, тобто &це реалізувати , щоб обчислити побітове логічне і ANDт.д.
  2. Для перерахунків (глава 7.11.2):
    вони реалізовані для виконання логічної операції базового типу перерахування.
  3. Для болів та нульових булів (глави 7.11.3 та 7.11.4):
    Результат не обчислюється за допомогою розрядних обчислень. Результат в основному шукають на основі значень двох операндів, оскільки кількість можливостей настільки мала.
    Оскільки обидва значення використовуються для пошуку, ця реалізація не є короткою ланцюгом.

31
Це також може бути зручно для перевірки, якщо щось є недійсним. Наприклад: if(op != null && op.CanExecute()). Оскільки друга причина не оцінюється, коли перша не відповідає дійсності, це справедливо.
TJHeuvel

2
@TJHeuvel: Це в основному те саме використання, яке я описав на своєму TryGetValueприкладі. Але так, це ще один хороший приклад цього.
Даніель Гілгарт

4
Хороша відповідь. Можливо, вам слід також додати приклад того, як &або |використовується аргументація, що не стосується bool (тобто, що роблять оператори) на користь всіх нових людей.
Забба

81

Дуже чітко пояснити, що це означає (хоча інші відповіді на це натякають - але, мабуть, використовуйте термінологію, яку ви не розумієте).

Наступний код:

if (a && b)
{
   Foo();
}

Справді складено до цього:

if (a)
{
    if (b)
    {
        Foo();
    }
}

Якщо наступний код складається саме так, як він представлений:

if (a & b)
{
   Foo();
}

Це називається коротке замикання. Загалом, ви завжди повинні користуватися &&і ||в своїх умовах.

Бонусні позначки: Є один сценарій, коли цього не слід робити. Якщо ви потрапили в ситуацію, коли продуктивність має вирішальне значення (а це наносекунд має вирішальне значення ), використовуйте коротке замикання лише тоді, коли потрібно (наприклад, nullперевірка) - оскільки коротке замикання - це гілка / стрибок; що може призвести до неправильного прогнозування вашого процесора; &набагато дешевше &&. Існує також сценарій, коли коротке замикання може насправді порушити логіку - подивіться на цю мою відповідь.

Діатриб / Монолог : Стосовно неправильного прогнозування галузі, яке найбільш блаженно ігнорується. Цитуючи Енді Ферта (який працює над іграми 13 років): "Це може бути нижчий рівень, що люди думають, що їм потрібно йти ... але вони помиляються. Розуміння того, як може працювати обладнання, яке ви програмуєте для гілок лікування впливати на продуктивність ВЕЛИЧЕЗНО ... набагато більше, ніж більшість програмістів можуть оцінити: смерть на тисячу скорочень "

  • Розробники ігор (та інші, що працюють в екстремальних умовах реального часу) переходять до того, як реструктуризують свою логіку, щоб краще відповідати передбачуваному. Про це також є докази в декомпільованому коді mscorlib.
  • Тільки тому, що .NET захищає вас від такого типу речей, не означає, що це не важливо. Неправильне прогнозування гілки є жахливо дорогим при 60 Гц; або при 10 000 запитів / секунду.
  • Intel не матиме інструментів для визначення місця помилкових прогнозів, а також Windows не матиме лічильник ефективності для цього, а також не було б слова, щоб описати це, якби це не було проблемою.
  • Незнання щодо нижчих рівнів та архітектури не робить того, хто їх усвідомлює не так.
  • Завжди намагайтеся зрозуміти обмеження обладнання, над яким ви працюєте.

Ось орієнтир для невіруючих. Найкраще запустити процес в RealTime / High, щоб пом’якшити планувальник, що має ефект: https://gist.github.com/1200737


7
Про "преміальні оцінки": Усі ми знаємо те, що є результатом передчасної оптимізації. :)
CVn

6
@Michael - ось чому «наносекунд вирішальний» є жирним шрифтом :). Розробники ігор AAA, як правило, турбуються про подібні речі - і ви ніколи не знаєте, хто прочитає відповіді; тому завжди найкраще документувати навіть прикордонні / крайні випадки.
Джонатан Дікінсон

1
Чи дійсний цей бонусний бал для C #? Я б подумав, що це не так, як інтерпретується MSIL, якщо тільки вираз не складено до машинного коду.
Джеремі Макгі

7
@Jeremy MSIL не інтерпретується.
Джонатан Дікінсон

2
@TheD повторна перевірка відповіді - я додав монолог про те, чому ви ПОТРІБНО турбуєтесь про це. І, FYI, (x && y)перекладається туди, LOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;де (x & y)перекладається LOAD x; LOAD y; AND; BRANCH_FALSE;. Одна гілка проти двох.
Джонатан Дікінсон

68

Логічний оператор ( ||і &&) проти побітових операторів ( |і &).

Найбільш важлива відмінність між логічним оператором і бітовим оператором полягає в тому, що логічний оператор приймає два булевих і виробляє булевий, а побітовий оператор приймає два цілі числа і виробляє ціле число (зверніть увагу: цілі числа означають будь-який інтегральний тип даних, а не просто int).

Щоб бути педантичним, побітовий оператор приймає біт-шаблон (наприклад, 01101011) і робить біт-розумним І / АБО на кожен біт. Так, наприклад, якщо у вас є два 8-бітні цілі числа:

a     = 00110010 (in decimal:    32+16+2   = 50)
b     = 01010011 (in decimal: 64+   16+2+1 = 83)
----------------
a & b = 00010010 (in decimal:       16+2   = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)

тоді як логічний оператор працює лише у bool:

a      = true
b      = false
--------------
a && b = false
a || b = true

По-друге, часто можна використовувати побітовий оператор на bool, оскільки true і false дорівнює 1 і 0 відповідно, і буває, що якщо ви перекладете true на 1, а false на 0, то виконайте побітову операцію, а потім перетворите ненульовий до істинного і від нуля до хибного; трапляється, що результат буде таким самим, якби ви щойно використовували логічний оператор (перевірте це на вправу).

Інша важлива відмінність також полягає в тому, що логічний оператор є короткозамкненим . Таким чином, у деяких колах [1] ви часто бачите людей, які роблять щось подібне:

if (person && person.punch()) {
    person.doVictoryDance()
}

що означає: "якщо людина існує (тобто не є нульовою), спробуйте вдарити її / її, і якщо удар вдасться (тобто повертає справжнє), тоді робіть танець перемоги" .

Якщо ви замість цього використовували побітовий оператор, це:

if (person & person.punch()) {
    person.doVictoryDance()
}

перекладається на: "якщо людина існує (тобто не є нульовою) і удар вдався (тобто повертає істину), тоді робіть танець перемоги" .

Зауважте, що в логічному операторі з коротким замиканням person.punch()код може взагалі не працювати, якщо він personє нульовим. Насправді в цьому конкретному випадку другий код створив би нульову посилання помилки, якщо він personє нульовим, оскільки він намагається викликати person.punch()незалежно від того, чи є людина нульовою чи ні. Така поведінка не оцінювання правильного операнда називається коротким замиканням .

[1] Деякі програмісти будуть шукати виклик функції, який має побічний ефект всередині ifвиразу, а для інших це загальна і дуже корисна ідіома.

Оскільки бітовий оператор одночасно працює над 32-бітовою машиною (якщо ви працюєте на 32-розрядній машині), це може призвести до більш елегантного та швидшого коду, якщо вам потрібно порівняти величезну кількість умов, наприклад

int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
    CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;

Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;

Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;

Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;

CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;

// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`

Зробити те саме з логічними операторами зажадає незручна кількість порівнянь:

Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;

Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;

Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;

CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch         = bar.rules.can_punch         && person.can_punch,
     cloc1.usable_abilities.can_kick          = bar.rules.can_kick          && person.can_kick,
     cloc1.usable_abilities.can_drink         = bar.rules.can_drink         && person.can_drink,
     cloc1.usable_abilities.can_sit           = bar.rules.can_sit           && person.can_sit,
     cloc1.usable_abilities.can_shoot_guns    = bar.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
     cloc1.usable_abilities.can_talk          = bar.rules.can_talk          && person.can_talk;

bool cloc2.usable_abilities.can_punch         = military.rules.can_punch         && person.can_punch,
     cloc2.usable_abilities.can_kick          = military.rules.can_kick          && person.can_kick,
     cloc2.usable_abilities.can_drink         = military.rules.can_drink         && person.can_drink,
     cloc2.usable_abilities.can_sit           = military.rules.can_sit           && person.can_sit,
     cloc2.usable_abilities.can_shoot_guns    = military.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc2.usable_abilities.can_talk          = military.rules.can_talk          && person.can_talk,
     cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;

Класичний приклад, коли використовуються бітові шаблони та бітовий оператор, є дозволами файлової системи Unix / Linux.


3
+1 для сторони впливає на проблему. Здивувавшись, що раніше не згадували
Конрад Фрікс

3
приклад здається трохи насильницьким, але здається, що інші відповіді занадто сильно орієнтовані на коротке замикання і недостатньо на різницю між оперуванням цілими числами і булевими.
R0MANARMY

Функція повинна бути зрозуміла до того, як деталі впровадження (коротке замикання / побічні ефекти) вступлять у дію. Радий, що ви прояснили головну різницю - булева та ціла логіка, а не коротке замикання.
Авель

@ROMANARMY - насильницький, я люблю іронію, яку дав твій монікер. Приємна робота
brumScouse

8

У випадку:

if (obj != null && obj.Property == true) { }

буде працювати, як очікувалося.

Але:

if (obj != null & obj.Property == true) { }

може потенційно викинути нульовий посилання на виключення.


2

Короткий і простий:

1 && 2= true,
оскільки
1 = true (ненульовий) у C
2 = true (ненульовий) у C

trueANDS логічно з trueдавати true.

Але

1 & 2= 0 = хибно,
оскільки
1 = 0001 у двійковій
2 = 0010 у двійковій

0001 AND порозрядно з 0010, щоб отримати 0000 = 0 в десятковій частині.

Аналогічно для || та | оператори теж ...!


2
-1: Ми говоримо про C # тут ... 1 && 2це незаконно в C #
Daniel Hilgarth

Але це надзвичайно важливий приклад, який пояснює, чому ви не можете просто обмінюватися & і && (про що, здається, думають багато людей).
bobobobo

1

&&- це версія короткого замикання &.

Якщо ми оцінюємо false & true, то вже з першого аргументу ми знаємо, що результат буде помилковим. &&Версія оператора буде повертати результат , як тільки він може, а не оцінювати цілий вираз. Існує також аналогічна Verion від |оператора ||.


1
if (list.Count() > 14 && list[14] == "foo")

є безпечним

if (list.Count() > 14 & list[14] == "foo")

може вийти з ладу, якщо список не має потрібного розміру.


Я не уявляю, що хтось може написати "if (list.Count ()> 14 & list [14] ==" foo ")" замість "if (list.Count ()> 14 && list [14] ==" foo ")". & просто і природно не можна використовувати для && в цьому випадку, навіть якщо & 's безперечно є безпечним (наприклад, список [1]).
Тянь До

1

Оператори C # повинні пояснити, чому:

По суті, наявність двох &або |s означає, що це умовно, а не логічно, тому ви можете сказати різницю між ними.

& Оператор має приклад використання цього&.


Обидва посилання (фактично) порушені (переадресація до "Документація на пенсію Visual Studio 2005" ).
Пітер Мортенсен

1

Гаразд, за номіналом

    Boolean a = true;
    Boolean b = false;

    Console.WriteLine("a({0}) && b({1}) =  {2}", a, b, a && b);
    Console.WriteLine("a({0}) || b({1}) =  {2}", a, b, a || b);
    Console.WriteLine("a({0}) == b({1}) =  {2}", a, b, a == b);

    Console.WriteLine("a({0}) & b({1}) =  {2}", a, b, a & b);
    Console.WriteLine("a({0}) | b({1}) =  {2}", a, b, a | b);
    Console.WriteLine("a({0}) = b({1}) =  {2}", a, b, a = b);

дають таку ж відповідь. Однак, як ви показали, якщо у вас є складніше питання:

if (a and b and c and d) ..

Якщо aце неправда і, можливо b, це функція, де вона має вимкнутись, підключитися до чогось, дістати це, зробити це, прийняти рішення .. навіщо турбуватися? Марно часу, ви знаєте, що це вже не вдалося. Навіщо змушувати машину вимикатись і робити зайві безглузді роботи?

Я завжди використовував, &&тому що я ставлю, швидше за все, перший збій, ерго, менше обчислень, перш ніж рухатись далі, коли немає сенсу. Якщо немає можливості передбачити менш вірогідні варіанти, наприклад, у вас є логічне обмеження виводу даних, щось на зразок:

if (limit && !MyDictionary.ContainsKey("name")) 
    continue;

Якщо це не так limit, не турбуйтеся перевірити ключ, який може зайняти більше часу.


1

При використанні в логічному виразі, такому як твердження if, &&бажано, оскільки воно перестане оцінювати вирази, як тільки виявиться перший хибний результат. Це можливо, оскільки помилкове значення призведе до того, що весь вираз буде хибним. Аналогічно (і знову ж у логічних виразах) ||є кращим, оскільки він припинить оцінювати вирази, як тільки зустрінеться з істинним виразом, оскільки будь-яке справжнє значення призведе до того, що весь вираз буде істинним.

Якщо ж висловлювання, які використовуються або підпорядковуються, або мають виправлення разом, мають побічні ефекти, і ви хочете, щоб усе це відбувалося в результаті вашого вираження (незалежно від результату логічного виразу), тоді &і його |можна було б використовувати. І навпаки, &&і ||оператори можуть бути корисними як захист від небажаних побічних ефектів (наприклад, нульовий покажчик, що спричиняє викид виключення).

Оператори &та |оператори також можуть використовуватися з цілими числами, і в цьому випадку вони створюють цілий результат, який представляє собою два операнди та -ed або -ed-ed разом на бітовому рівні. Це може бути корисно, коли двійкові біти цілого значення використовуються як масив істинних та хибних значень. Щоб перевірити, чи певний біт увімкнено чи вимкнено, бітова маска є побітовою та е-ед зі значенням. Щоб трохи увімкнути, та сама маска може бути побітовою або надісланою зі значенням. Нарешті, щоб трохи вимкнути, побітове доповнення (використання ~) маски є побітовим і -ед зі значенням.

int a = 0; // 0 means all bits off
a = a | 4; // set a to binary 100
if ((a & 4) != 0) {
    // will do something
}
a = a & (~4) // turn bit off again, a is now 000

У інших мовах, крім C #, слід бути обережними з логічними та побітовими режимами & і |. У наведеному вище коді ifумовне вираження твердження (a & 4) != 0є безпечним способом виразити цю умову, але в багатьох мовах, як і С, умовні висловлювання можуть просто розцінювати нульові цілі значення як помилкові, а ненульові цілочисельні значення - як істинні. (Причина цього стосується наявних інструкцій процесора умовної гілки та їх відношення до нульового прапора, який оновлюється після кожної цілочисельної операції.) ìfТест заяви на нуль може бути видалений, а умова може бути скорочена до (a & 4).

Це може спричинити плутанину та, можливо, навіть проблеми, коли вирази поєднуються за допомогою побітових та зворотних значень оператора, у яких немає бітів, які вирівнюються. Розглянемо наступний приклад, де бажані побічні ефекти двох функцій, перш ніж перевірити, чи вони обидві були успішними (як визначено ними, повертаючи ненульове значення):

if (foo() & bar()) {
    // do something
}

У C, якщо foo()повертає 1 і bar()повертає 2, "щось" не буде зроблено, оскільки 1 & 2дорівнює нулю.

C # вимагає умовних висловлювань, таких ifяк булева oeprand, і мова не дозволяє цілому значенню присвоїти булеве значення. Таким чином, наведений вище код створює помилки компілятора. Правильніше було б висловитись так:

if (foo() != 0 & bar() != 0) {
    // do something
}

1

Якщо ви програміст старого часу C, будьте обережні . C # дійсно мене здивував.

MSDN каже для |оператора:

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

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

&&і ||мають коротке замикання. &і |оцінити обидва операнди.

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

Причина полягає в тому, що я б міркував так: Оскільки в C немає справжнього булевого типу, ви можете використовувати побітовий оператор |і його результат оцінювати як правду або хибність в умовах if. Але це неправильне ставлення до C #, оскільки для булевих типів вже існує особливий випадок.


0

Це важливо, оскільки якщо вартість оцінки bool2 (наприклад) висока, але bool1 помилкова, то ви заощадили собі непоганий обчислення, використовуючи && over &


0

Тому що &&і ||використовуються для контролю потоку так само, як if/elseє. Це не завжди про умовні умови. Це цілком розумно , щоб написати в заяві, не як ifабо в whileумовному, в наступному:

 a() && b() && c() && d();

або навіть

 w() || x() || y() || z();

Це не просто те, що їх легше набрати, ніж еквівалентні if/elseверсії; їх також набагато простіше читати та розуміти.


0

&& і & означають дві дуже різні речі і дають вам дві різні відповіді.

1 && 2врожайність 1 ("справжня")
1 & 2врожайність 0 ("хибна")

&&є логічним оператором - це означає, що "true, якщо обидва операнди є істинними"
&- це побітове порівняння. Це означає "скажіть мені, який з бітів встановлений в обох операндах"


2
Питання стосується C #. У C # немає способу привласнити число до bool, тому 0 не є "хибним", а ненульове значення не є "істинним"; просто немає еквівалентності.
Nate CK

Щоб перетворити число в bool, таким чином, що 1 означає істину, а 0 означає хибність, скажіть "n! = 0" (я припускаю ... я не дуже знайомий з C #). Насправді я хотів відмовитись від цього коментаря, оскільки він недостатньо досліджений, і я не думаю, що він корисний або справді має відношення до попереднього коментаря, коли я думаю про нього більше, але випадково натиснув Enter і тепер не думаю, що зможу скасуйте його, так що ви йдіть, на що б то не варто :-)
Дон Хетч

1 && 2дає помилку компілятора: "Оператор помилки 4" && "не може бути застосований до операндів типів" int "та" int ""
Пітер Мортенсен

0

Найшвидший (і злегка скинутий) спосіб пояснити це людям, які НЕ ПОТРІБНІ знати точні операції коду при цьому:

&& проводить перевірку кожного з цих умов, поки не виявить помилковий і не поверне весь результат як хибний

|| проводить перевірку кожної з цих умов, поки вона не знайде істину і не поверне весь результат як істинний.

& робить MATHS на основі апона БОТ / ВСІ умови та вирішення результатів.

| виконує на основі MATHS апон БОТ / ВСІ умови та вирішує результат.

Я ніколи не стикався з моментом, коли мені потрібно було використовувати & або | в заяві if. Я здебільшого використовую його для розрізання шістнадцяткових значень у складові кольори за допомогою бітового зсуву.

EG:

r = fullvalue >> 0xFF & 0xFF;
g = fullvalue >> 0xF & 0xFF;
b = fullvalue & 0xFF;

У рамках цієї операції "& 0xFF" змушує дивитися лише на бінарне значення. Я особисто не знайшов використання для | все ж таки.


0

Просто,

if exp1 && exp2

якщо exp1 flase не перевіряє exp2

але

if exp1 & exp2

якщо exp1 - falseАбо true перевірити exp2

і рідко люди використовують, &тому що вони рідко хочуть перевірити exp2, якщо є exp1false

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