Логическая переменная в c примеры коде. Логические операторы в си. Порядок выполнения логических операторов

Теги: Си логические операторы, логическое отрицание, логическое НЕ, !, логическое ИЛИ, логическое сложение, OR, логическое умножение, логическое И, AND, порядок выполнения логических операторов

Логические операторы

Л огические операторы – это операторы, которые принимают в качестве аргументов логические значений (ложь или истину) и возвращают логическое значение. Как и обычные операторы, они могут быть одноместными (унарными, т.е. принимать один аргумент), двуместными (бинарные, принимают два аргумента), трёхместными и т.д.

Особенностью языка си является то, что в нём нет типа, хранящего булево значение (ложь или истину). В си ложью (логическим нулём) считается целочисленный 0, а любое ненулевое целое будет логической истиной. Например

#include #include void main() { char boolValue = -71; if (boolValue) { printf("boolValue is true"); } else { printf("boolValue is false"); } _getch(); }

Логические значения обычно порождаются операторами сравнения (==, !=, >, <, >=. <=).

В языке си представлено три логических оператора: И, ИЛИ и НЕ. Начнём с самого простого

Логическое отрицание

О ператор НЕ (NOT) используется для того, чтобы инвертировать значение аргумента. Т.е., если ему передали истину, то он вернёт ложь, если получил ложь в качестве аргумента, то вернёт истину.

Логический оператор НЕ
X NOT X
0 1
1 0

В си отрицание представлено оператором!. Например

#include #include void main() { int i = 0; if (i) { printf("i is true\n"); } if (!i) { printf("i is not true\n"); } if (!!i) { printf("i is not not true\n"); } if (!!!i) { printf("i is not not not true\n"); } _getch(); }

Как и в обычной логике, здесь действует закон двойного отрицания – отрицание отрицания можно опустить.

Логическое И

О ператор И (AND, логическое умножение) возвращает истину тогда и только тогда, когда оба аргумента являются истиной.


Логический оператор И
X Y X AND Y
0 0 0
0 1 0
1 0 0
1 1 1

В си логическое умножение представлено оператором &&. Например, задача – в кружок военных спейсмаринов допускаются только совершеннолетние граждане мужского пола. То есть, претендентом может стать только тот, для которого одновременно два условия являются истиной

#include void main() { char gender; unsigned int age; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age\n"); scanf("%u", &age); if (gender == "M" && age > 17) { printf("Wellcome"); } else { printf("Go away"); } _getch(); }

Оператор И может применяться последовательно к нескольким аргументам. Для него действует ассоциативный и коммутативный законы. Усовершенствуем программу, будем также вводить рост:

#define _CRT_SECURE_NO_WARNINGS #include #include void main() { char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age\n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if (gender == "M" && age > 17 && height >= 180) { printf("Wellcome"); } else { printf("Go away"); } _getch(); }

Также условие могло быть записано

(gender == "M" && age > 17) && height >= 180

Gender == "M" && (age > 17 && height >= 180)

(age > 17 && height >= 180) && gender == "M"

Логическое ИЛИ

О ператор логическое ИЛИ (логическое сложение, OR) истинен тогда, когда истиной является хотя бы один его аргумент.


Логический оператор ИЛИ
X Y X OR Y
0 0 0
0 1 1
1 0 1
1 1 1

В си ИЛИ представлен оператором ||. Например, усовершенствуем программу: теперь пол можно вводить как большой, так и маленькой буквой

#define _CRT_SECURE_NO_WARNINGS #include #include void main() { char genderInput; char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &genderInput); printf("Enter age\n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if (genderInput == "M" || genderInput == "m") { gender = 1; } else { gender = 0; } if ((age > 17 && height >= 180) && gender) { printf("Wellcome"); } else { printf("Go away"); } _getch(); }

Как и в случае оператора И, ИЛИ коммутативен и ассоциативен.

Операторы можно перемешивать друг с другом, создавая сложные операторы

#define _CRT_SECURE_NO_WARNINGS #include #include void main() { char gender; unsigned int age; unsigned int height; printf("Enter gender ("M" or "F")\n"); scanf("%c", &gender); printf("Enter age\n"); scanf("%u", &age); printf("Enter height\n"); scanf("%u", &height); if ((age > 17 && height >= 180) && (gender == "M" || gender == "m")) { printf("Wellcome"); } else { printf("Go away"); } _getch(); }

Стоит только помнить о том, что оператор отрицания имеет больший приоритет, чем И или ИЛИ, поэтому будет выполняться в первую очередь. Если может случиться ситуация, когда порядок выполнения не ясен, определите его с помощью скобок.

Пример: закон де-Моргана. Чтобы сменить И на ИЛИ (или наоборот), необходимо инвертировать значения всех операндов, заменить И на ИЛИ (или ИЛИ на И) и инвертировать конечный результат. В случае с нашим условием

(age > 17 && height >= 180) && (gender == "M" || gender == "m")

Рассмотрим сначала кусок

(age > 17 && height >= 180)

Меняем все значения на обратные

(!(age > 17) && !(height >= 180))

заменяем оператор && на ||

(!(age > 17) || !(height >= 180))

и инвертируем ответ

!(!(age > 17) || !(height >= 180))

Как видим, результат тот же. Очевидно, что

!(age > 17)

эквивалентно

Age <= 17

Таким образом, изменим условие

!(age <= 17 || height < 180)

Поменяем таким же образом вторую скобку

(gender == "M" || gender == "m")

!(gender != "M" && gender != "m")

!(age <= 17 || height < 180) && !(gender != "M" && gender != "m")

Теперь можно применить это же правило и для всего выражения

!((age <= 17 || height < 180) || (gender != "M" && gender != "m"))

Порядок выполнения логических операторов

Р ассмотрим выражение

A && b && c && d

где a, b, c, d – логические значения. Всё выражение равно истине тогда и только тогда, когда все операнды истинны. Если хотя бы один из операндов ложь, то остальные уже не важны. Поэтому, для оптимизации работы, вычисление происходит слева направо и останавливается, как только был найден первый операнд, равный нулю.

В си оператор присваивания может возвращать значение. Иногда он используется непосредственно в условии:

#define _CRT_SECURE_NO_WARNINGS #include #include #include void main() { int a = 0; int *p = &a; if (a && (p = (int*) malloc(sizeof(int) * 2))) { printf("memory was allocated"); } free(p); _getch(); }

В данном случае, оператор malloc не будет выполнен, так как первый операнд a равен 0 (соответственно, всё выражение равно нулю). Таким образом, оператор free попытается очистить память, которую не может очистить (т.к. p продолжит ссылаться на a). Если же мы поменяем a = 1, то всё отработает без проблем.

То же самое происходит и при выполнение ||. Выражение

A || b || c || d

выполняется слева направо до тех пор, пока не встретит первое ненулевое значение. После этого выполнение останавливается, так как известно, что всё выражение равно истине.

Примечание. Все операции в результате дают значение типа bool

Операции сравнения и логические операции в результате дают значение типа bool, то есть true или false. Если же такое выражение встречается в контексте, требующем целого значения, true преобразуется в 1, а false – в 0. Вот фрагмент кода, подсчитывающего количество элементов вектора, меньших некоторого заданного значения:

Vector::iterator iter = ivec.beg-in() ; while (iter != ivec.end()) { // эквивалентно: e1em_cnt = e1em_cnt + (*iter < some_va1ue) // значение true/false выражения *iter < some_va1ue // превращается в 1 или 0 e1em_cnt += *iter < some_va1ue; ++iter; }

Мы просто прибавляем результат операции “меньше” к счетчику. (Пара += обозначает составной оператор присваивания, который складывает операнд, стоящий слева, и операнд, стоящий справа. То же самое можно записать более компактно: elem_count = elem_count + n. Мы рассмотрим такие операторы в разделе 4.4.)
Логическое И (&&) возвращает истину только тогда, когда истинны оба операнда. Логическое ИЛИ (||) дает истину, если истинен хотя бы один из операндов. Гарантируется, что операнды вычисляются слева направо и вычисление заканчивается, как только результирующее значение становится известно. Что это значит? Пусть даны два выражения:

Expr1 && expr2 expr1 || expr2

Если в первом из них expr1 равно false, значение всего выражения тоже будет равным false вне зависимости от значения expr2, которое даже не будет вычисляться. Во втором выражении expr2 не оценивается, если expr1 равно true, поскольку значение всего выражения равно true вне зависимости от expr2.
Подобный способ вычисления дает возможность удобной проверки нескольких выражений в одном операторе AND:

While (ptr != О && ptr->va1ue < upperBound && ptr->va1ue >= 0 && notFound(ia[ ptr->va1ue ])) { ... }

Указатель с нулевым значением не указывает ни на какой объект, поэтому применение к нулевому указателю операции доступа к члену вызвало бы ошибку (ptr->value). Однако, если ptr равен 0, проверка на первом шаге прекращает дальнейшее вычисление подвыражений. Аналогично на втором и третьем шагах проверяется попадание величины ptr->value в нужный диапазон, и операция взятия индекса не применяется к массиву ia, если этот индекс неправилен.
Операция логического НЕ дает true, если ее единственный оператор равен false, и наоборот. Например:

Bool found = false; // пока элемент не найден // и ptr указывает на объект (не 0) while (! found && ptr) { found = 1ookup(*ptr); ++ptr; }

Подвыражение

Дает true, если переменная found равна false. Это более компактная запись для

Found == false

Аналогично

Эквивалентно более длинной записи

If (found == true)

Использование операций сравнения достаточно очевидно. Нужно только иметь в виду, что, в отличие от И и ИЛИ, порядок вычисления операндов таких выражений не определен. Вот пример, где возможна подобная ошибка:

// Внимание! Порядок вычислений не определен! if (ia[ index++ ] < ia[ index ]) // поменять местами элементы

Программист предполагал, что левый операнд оценивается первым и сравниваться будут элементы ia и ia. Однако компилятор не гарантирует вычислений слева направо, и в таком случае элемент ia может быть сравнен сам с собой. Гораздо лучше написать более понятный и машинно-независимый код:

If (ia[ index ] < ia[ index+1 ]) // поменять местами элементы ++index;

Еще один пример возможной ошибки. Мы хотели убедиться, что все три величины ival, jval и kval различаются. Где мы промахнулись?

// Внимание! это не сравнение 3 переменных друг с другом if (ival != jva1 != kva1) // do something ...

Значения 0, 1 и 0 дают в результате вычисления такого выражения true. Почему? Сначала проверяется ival != jval, а потом итог этой проверки (true/false – преобразованной к 1/0) сравнивается с kval. Мы должны были явно написать:
if (ival != jva1 && ival != kva1 && jva1 != kva1)
// сделать что-то...

Упражнение 4.4

Найдите неправильные или непереносимые выражения, поясните. Как их можно изменить? (Заметим, что типы объектов не играют роли в данных примерах.)
(a) ptr->iva1 != 0
(с) ptr != 0 && *ptr++
(e) vec[ iva1++ ] <= vec[ ival ];
(b) ival != jva1 < kva1 (d) iva1++ && ival

Упражнение 4.5

Язык С++ не диктует порядок вычисления операций сравнения для того, чтобы позволить компилятору делать это оптимальным образом. Как вы думаете, стоило бы в данном случае пожертвовать эффективностью, чтобы избежать ошибок, связанных с предположением о вычислении выражения слева направо?

Любое выражение языка состоит из операндов (переменных, констант и др.), соединенных знаками операций. Знак операции - это символ или группа символов, которые сообщают компилятору о необходимости выполнения определенных арифметических, логических или других действий.

Операции выполняются в строгой последовательности. Величина, определяющая преимущественное право на выполнение той или иной операции, называется приоритетом. В табл. 2 перечислены различные операции языка СИ (C). Их приоритеты для каждой группы одинаковы (группы выделены цветом). Чем большим преимуществом пользуется соответствующая группа операций, тем выше она расположена в таблице. Порядок выполнения операций может регулироваться с помощью круглых скобок.

Таблица 2 - операции

Знак операции

Назначение операции

Вызов функции

Выделение элемента массива

Выделение элемента записи

Выделение элемента записи

Логическое отрицание

Поразрядное отрицание

Изменение знака

Увеличение на единицу

Уменьшение на единицу

Взятие адреса

Обращение по адресу

Преобразование типа (т.е. (float) a)

Определение размера в байтах

Умножение

Определение остатка от деления

Сложение

Вычитание

Сдвиг влево

Сдвиг вправо

Меньше, чем

Меньше или равно

Больше, чем

Больше или равно

Поразрядное логическое "И"

Поразрядное исключающее "ИЛИ"

Поразрядное логическое "ИЛИ"

Логическое "И"

Логическое "ИЛИ"

Условная (тернарная) операция

Присваивание

+=, - =, *=, /=, %=, <<=,
>>=, &=, |=, ^=

Бинарные операции (например, а *= b
(т.е. a = a * b) и т.д.)

Операция запятая

Оператор в языке Си (C)

Для исключения путаницы в понятиях "операция" и "оператор", отметим, что оператор - это наименьшая исполняемая единица программы. Различают операторы выражения, действие которых состоит в вычислении заданных выражений (например: a = sin(b)+c; j++;), операторы объявления, составные операторы, пустые операторы, операторы метки, цикла и т.д. Для обозначения конца оператора в языке СИ (C)используется точка с запятой. Что касается составного оператора (или блока), представляющего собой набор логически связанных операторов, помещенных между открывающей ({) и закрывающей (}) фигурными скобками ("операторными скобками"), то за ним точка с запятой не ставится. Отметим, что блок отличается от составного оператора наличием определений в теле блока.

Характеристика основных операций языка Си (C)

Охарактеризуем основные операции языка СИ (C).

Операция присваивания

Сначала рассмотрим одну из них - операцию присваивания (=). Выражение вида

присваивает переменной х значение переменной у. Операцию "=" разрешается использовать многократно в одном выражении, например:

x = y = z = 100;

Различают унарные и бинарные операции. У первых из них один операнд, а у вторых - два. Начнем их рассмотрение с операций, отнесенных к первой из следующих традиционных групп:

Арифметические операции.

Логические операции и операции отношения.

Операции с битами.

Арифметические операции задаются следующими символами (табл. 2): +, -, *, /, % . Последнюю из них нельзя применять к переменным вещественного типа. Например:

a = b + c;
x = y - z;
r = t * v;
s = k / l;
p = q % w;

Логические операции

Логические операции отношения задаются следующими символами (см. табл. 2): && ("И"), || ("ИЛИ"), ! ("НЕ"), >, >=, <, <= , = = (равно), != (не равно). Традиционно эти операции должны давать одно из двух значений: истину или ложь. В языке СИ (C)принято следующее правило: истина - это любое ненулевое значение; ложь - это нулевое значение. Выражения, использующие логические операции и операции отношения, возвращают 0 для ложного значения и 1 для истинного. Ниже приводится таблица истинности для логических операций.

Битовые операции можно применять к переменным, имеющим типы int, char, а также их вариантам (например, long int). Их нельзя применять к переменным типов float, double, void (или более сложных типов). Эти операции задаются следующими символами: ~ (поразрядное отрицание), << (сдвиг влево), >> (сдвиг вправо), & (поразрядное "И"), ^ (поразрядное исключающее "ИЛИ"), | (поразрядное "ИЛИ").

Примеры: если a=0000 1111 и b=1000 1000, то

~a = 1111 0000,
a << 1 = 0001 1110,
a >> 1 = 0000 0111,
a & b = 0000 1000,
a ^ b = 1000 0111,
a | b = 1000 1111.

В языке предусмотрены две нетрадиционные операции инкремента (++) и декремента (--). Они предназначены для увеличения и уменьшения на единицу значения операнда. Операции ++ и -- можно записывать как перед операндом, так и после него. В первом случае (++n или --n) значение операнда (n) изменяется перед его использованием в соответствующем выражении, а во втором (n++ или n--) - после его использования. Рассмотрим две следующие строки программы:

a = b + c++;
a1 = b1 + ++c1;

Предположим, что b = b1 = 2, c = c1 = 4. Тогда после выполнения операций: a = 6, b = 2, c = 5, a1 = 7, b1 = 2, c1 = 5.

Широкое распространение находят также выражения с еще одной нетрадиционной тернарной или условной операцией?: . В формуле

y = a, если x не равно нулю (т.е. истинно), и y = b, если х равно нулю (ложно). Следующее выражение

y = (a>b) ? a: b;

позволяет присвоить переменной у значение большей переменной (а или b), т.е. y = max(a, b).

Еще одним отличием языка является то, что выражение вида а = а + 5; можно записать в другой форме: a += 5;. Вместо знака + можно использовать и символы других бинарных операций (см. табл. 2).

Другие операции из табл. 2 будут описаны в последующих параграфах.

Циклы организуются, чтобы выполнить некоторый оператор или группу операторов определенное число раз. В языке СИ (C)три оператора цикла: for, while и do - while. Первый из них формально записывается, в следующем виде:

for (выражение_1; выражение_2; выражение_3) тело_цикла

Тело цикла составляет либо один оператор, либо несколько операторов, заключенных в фигурные скобки { ... } (после блока точка с запятой не ставится). В выражениях 1, 2, 3 фигурирует специальная переменная, называемая управляющей. По ее значению устанавливается необходимость повторения цикла или выхода из него.

Выражение_1 присваивает начальное значение управляющей переменной, выражение_З изменяет его на каждом шаге, а выражение_2 проверяет, не достигло ли оно граничного значения, устанавливающего необходимость выхода из цикла.

for (i = 1; i < 10; i++)

for (сh = "a"; ch != "p";) scanf ("%c", &ch);

/* Цикл будет выполняться до тех пор, пока с клавиатуры

не будет введен символ "p" */

Любое из трех выражений в цикле for может отсутствовать, однако точка с запятой должна оставаться. Таким образом, for (; ;) {...} - это бесконечный цикл, из которого можно выйти лишь другими способами.

В языке СИ (C)принято следующее правило. Любое выражение с операцией присваивания, заключенное в круглые скобки, имеет значение, равное присваиваемому. Например, выражение (а=7+2) имеет значение 9. После этого можно записать другое выражение, например: ((а=7+2)<10), которое в данном случае будет всегда давать истинное значение. Следующая конструкция:

((сh = getch()) == "i")

позволяет вводить значение переменной сh и давать истинный результат только тогда, когда введенным значением является буква "i". В скобках можно записывать и несколько формул, составляющих сложное выражение. Для этих целей используется операция запятая. Формулы будут вычисляться слева направо, и все выражение примет значение последней вычисленной формулы. Например, если имеются две переменные типа char, то выражение

z = (х = у, у = getch());

определяет следующие действия: значение переменной у присваивается переменной х; вводится символ с клавиатуры и присваивается переменной у; z получает значение переменной у. Скобки здесь необходимы, поскольку операция запятая имеет более низкий приоритет, чем операция присваивания, записанная после переменной z. Операция запятая находит широкое применение для построения выражений цикла for и позволяет параллельно изменять значения нескольких управляющих переменных.

Допускаются вложенные конструкции, т.е. в теле некоторого цикла могут встречаться другие операторы for.

Оператор while формально записывается в таком виде:

while (выражение) тело_цикла

Выражение в скобках может принимать ненулевое (истинное) или нулевое (ложное) значение. Если оно истинно, то выполняется тело цикла и выражение вычисляется снова. Если выражение ложно, то цикл while заканчивается.

Оператор do-while формально записывается следующим образом:

do {тело_цикла} while (выражение);

Основным отличием между циклами while и do - while является то, что тело в цикле do - while выполняется по крайней мере один раз. Тело цикла будет выполняться до тех пор, пока выражение в скобках не примет ложное значение. Если оно ложно при входе в цикл, то его тело выполняется ровно один раз.

Допускается вложенность одних циклов в другие, т.е. в теле любого цикла могут появляться операторы for, while и do - while.

В теле цикла могут использоваться новые операторы break и continue. Оператор break обеспечивает немедленный выход из цикла, оператор continue вызывает прекращение очередной и начало следующей итерации.

Операторы условных и безусловных переходов

Для организации условных и безусловных переходов в программе на языке СИ (C)используются операторы: if - else, switch и goto. Первый из них записывается следующим образом:

if (проверка_условия) оператор_1; else оператор_2;

Если условие в скобках принимает истинное значение, выполняется оператор_1, если ложное - оператор_2. Если вместо одного необходимо выполнить несколько операторов, то они заключаются в фигурные скобки. В операторе if слово else может отсутствовать.

В операторе if - else непосредственно после ключевых слов if и else должны следовать другие операторы. Если хотя бы один из них является оператором if, его называют вложенным. Согласно принятому в языке СИ (C)соглашению слово else всегда относится к ближайшему предшествующему ему if.

Оператор switch позволяет выбрать одну из нескольких альтернатив. Он записывается в следующем формальном виде:

switch (выражение)

case константа_1: операторы_1;

case константа_2: операторы_2;

........ ........

default: операторы_default;

Здесь вычисляется значение целого выражения в скобках (его иногда называют селектором) и оно сравнивается со всеми константами (константными выражениями). Все константы должны быть различными. При совпадении выполнится соответствующий вариант операторов (один или несколько операторов). Вариант с ключевым словом default реализуется, если ни один другой не подошел (слово default может и отсутствовать). Если default отсутствует, а все результаты сравнения отрицательны, то ни один вариант не выполняется.

Для прекращения последующих проверок после успешного выбора некоторого варианта используется оператор break, обеспечивающий немедленный выход из переключателя switch.

Допускаются вложенные конструкции switch.

Рассмотрим правила выполнения безусловного перехода, который можно представить в следующей форме:

goto метка;

Метка - это любой идентификатор, после которого поставлено двоеточие. Оператор goto указывает, что выполнение программы необходимо продолжить начиная с оператора, перед которым записана метка. Метку можно поставить перед любым оператором в той функции, где находится соответствующий ей оператор goto. Ее не надо объявлять.

Турбо отладчик полностью поддерживает синтаксис выражений языка СИ (C). Выражение состоит из смеси операций, строк, переменных

Над объектами в языке Си могут выполняться различные операции:

  • операции присваивания;
  • операции отношения;
  • арифметические;
  • логические;
  • сдвиговые операции.

Результатом выполнения операции является число.

Операции могут быть бинарными или унарными.
Бинарные операции выполняются над двумя объектами, унарные - над одним.

Операция присваивания

Операция присваивания обозначается символом = и выполняется в 2 этапа:

  • вычисляется выражение в правой части;
  • результат присваивается операнду, стоящему в левой части:

объект = выражение;

Пример:

int a = 4; // переменной a присваивается значение 4
int b;
b = a + 2; // переменной b присваивается значение 6, вычисленное в правой части

В случае если объекты в левой и правой части операции присваивания имеют разные типы используется операция явного приведения типа.
объект = (тип)выражение;

Пример:

float a = 241.5;
// Перед вычислением остатка от деления a приводится к целому типу
int b = (int )a % 2; // b = 1

Операции отношения

Основные операции отношения:

  • == эквивалентно - проверка на равенство;
  • != не равно - проверка на неравенство;
  • < меньше;
  • > больше;
  • <= меньше или равно;
  • >= больше или равно.

Операции отношения используются при организации условий и ветвлений. Результатом этих операций является 1 бит, значение которого равно 1 , если результат выполнения операции — истина, и равно 0 , если результат выполнения операции — ложь.

Арифметические операции

Основные бинарные операции, расположенные в порядке уменьшения приоритета:

  • * — умножение;
  • / — деление;
  • + — сложение;
  • — вычитание;
  • % — остаток от целочисленного деления.

Основные унарные операции:

  • ++ — инкрементирование (увеличение на 1);
  • -- — декрементирование (уменьшение на 1);
  • — изменение знака.

Результат вычисления выражения, содержащего операции инкрементирования или декрементирования, зависит от того, где расположен знак операции (до объекта или после него). Если операция расположена до объекта, то сначала происходит изменение значения переменной на 1, а потом это значение используется для выполнения следующих операций. Если операция ++ или расположена после переменной, то сначала выполняется операция, а потом значение переменной изменяется на 1.

Пример :

Бинарные арифметические операции могут быть объединены с операцией присваивания:

  • объект *= выражение; // объект = объект * выражение
  • объект /= выражение; // объект = объект / выражение
  • объект += выражение; // объект = объект + выражение
  • объект -= выражение; // объект = объект — выражение
  • объект %= выражение; // объект = объект % выражение

Логические операции

Логические операции делятся на две группы:

  • условные;
  • побитовые.

Условные логические операции чаще всего используются в операциях проверки условия if и могут выполняться над любыми объектами. Результат условной логической операции:

  • 1 если выражение истинно;
  • 0 если выражение ложно.

Вообще, все значения, отличные от нуля, интерпретируются условными логическими операциями как истинные.

Основные условные логические операции:

  • && — И (бинарная) - требуется одновременное выполнение всех операций отношения;
  • || — ИЛИ (бинарная) - требуется выполнение хотя бы одной операции отношения;
  • ! — НЕ (унарная) - требуется невыполнение операции отношения.

Побитовые логические операции оперируют с битами, каждый из которых может принимать только два значения: 0 или 1.

Основные побитовые логические операции в языке Си:

  • & конъюнкция (логическое И) — бинарная операция, результат которой равен 1 только когда оба операнда единичны (в общем случае — когда все операнды единичны);
  • | дизъюнкция (логическое ИЛИ) — бинарная операция, результат которой равен 1 когда хотя бы один из операндов равен 1;
  • ~ инверсия (логическое НЕ) — унарная операция, результат которой равен 0 если операнд единичный, и равен 1, если операнд нулевой;
  • ^ исключающее ИЛИ — бинарная операция, результат которой равен 1, если только один из двух операндов равен 1 (в общем случае если во входном наборе операндов нечетное число единиц).

Для каждого бита результат выполнения операции будет получен в соответствии с таблицей.

a b a & b a | b ~a a ^ b
0 0 0 0 1 0
0 1 0 1 1 1
1 0 0 1 0 1
1 1 1 1 0 0

Пример :

1
2
3
4
5
6
7

unsigned char a = 14; // a = 0000 1110
unsigned char b = 9; // b = 0000 1001
unsigned char c, d, e, f;
c = a & b; // c = 8 = 0000 1000
d = a | b; // d = 15 = 0000 1111
e = ~a; // e = 241 = 1111 0001
f = a ^ b; // f = 7 = 0000 0111


Побитовые операции позволяют осуществлять установку и сброс отдельных битов числа. С этой целью используется маскирование битов . Маски, соответствующие установке каждого бита в байте, представлены в таблице

Бит Маска
0 0x01
1 0x02
2 0x04
3 0x08
4 0x10
5 0x20
6 0x40
7 0x80

Для установки определенного бита необходимо соответствующий бит маски установить в 1 и произвести операцию побитового логического ИЛИ с константой, представляющей собой маску.

Операторы отношения и логические операторы

В обозначениях оператор отношения и логический оператор термин отношения означает взаимосвязь, которая может существовать между двумя значениями, а термин логический - взаимосвязь между логическими значениями "истина" и "ложь". И поскольку операторы отношения дают истинные или ложные результаты, то они нередко применяются вместе с логическими операторами. Именно по этой причине они и рассматриваются совместно.

Ниже перечислены операторы отношения:

К числу логических относятся операторы, приведенные ниже:

Результатом выполнения оператора отношения или логического оператора является логическое значение типа bool .

В целом, объекты можно сравнивать на равенство или неравенство, используя операторы отношения == и!=. А операторы сравнения, = могут применяться только к тем типам данных, которые поддерживают отношение порядка. Следовательно, операторы отношения можно применять ко всем числовым типам данных. Но значения типа bool могут сравниваться только на равенство или неравенство, поскольку истинные (true) и ложные (false) значения не упорядочиваются. Например, сравнение true > false в C# не имеет смысла.

Рассмотрим пример программы, демонстрирующий применение операторов отношения и логических операторов:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string args) { short d = 10, f = 12; bool var1 = true, var2 = false; if (d f) Console.WriteLine("d > f"); // Сравниванием переменные var1 и var2 if (var1 & var2) Console.WriteLine("Данный текст не выведется"); if (!(var1 & var2)) Console.WriteLine("!(var1 & var2) = true"); if (var1 | var2) Console.WriteLine("var1 | var2 = true"); if (var1 ^ var2) Console.WriteLine("var1 ^ var2 = true"); Console.ReadLine(); } } }

Логические операторы в C# выполняют наиболее распространенные логические операции. Тем не менее существует ряд операций, выполняемых по правилам формальной логики. Эти логические операции могут быть построены с помощью логических операторов, поддерживаемых в C#. Следовательно, в C# предусмотрен такой набор логических операторов, которого достаточно для построения практически любой логической операции, в том числе импликации. Импликация - это двоичная операция, результатом которой является ложное значение только в том случае, если левый ее операнд имеет истинное значение, а правый - ложное. (Операция импликации отражает следующий принцип: истина не может подразумевать ложь.)

Операция импликации может быть построена на основе комбинации логических операторов! и |:

Укороченные логические операторы

В C# предусмотрены также специальные, укороченные , варианты логических операторов И и ИЛИ, предназначенные для получения более эффективного кода. Поясним это на следующих примерах логических операций. Если первый операнд логической операции И имеет ложное значение (false), то ее результат будет иметь ложное значение независимо от значения второго операнда. Если же первый операнд логической операции ИЛИ имеет истинное значение (true), то ее результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода .

Укороченная логическая операция И выполняется с помощью оператора && , а укороченная логическая операция ИЛИ - с помощью оператора || . Этим укороченным логическим операторам соответствуют обычные логические операторы & и |. Единственное отличие укороченного логического оператора от обычного заключается в том, что второй его операнд вычисляется только по мере необходимости.