Операции в языке си. Логические операторы в си Логические операторы в с

 Синтаксис оператора присвоения языка СИ имеет вид:
  LValue = RValue;
  LValue – это то куда будет записано значение. В роли такого объекта в СИ может выступать только переменная.
 RValue – это то значение чего мы запишем в LValue. А в этой роли могут выступать такие объекты как:
  переменная,
  константа,
  оператор вызова функции,
  математическое или логическое выражение.
 Примеры присвоений
  int a, b, c;
  double x, y;
  a = 5; b = 4; c = a + b;
  x = 5.0; y = exp(x);

Усовершенствованные операторы присвоений в СИ

 В СИ присутствуют так называемые усовершенствованные операторы присвоения, выглядят они так:
  LValue X= RValue; где X – это одна операция из набора: + - * / % ^ & | >. это является аналогией оператора присвоения:
  LValue = LValue X RValue;
 К примеру:
  a += b; ≡ a = a + b;
 В языке СИ все математические операции можно разделить на 2 группы:
  1. математические операции для вещественных и целочисленных вычислений;
  2. математические операции только для целочисленных вычислений.

К математическим операциям для вещественных и целочисленных вычислений языка СИ относят обычные арифметические операции:
  сложения (+),
  вычитания (-),
  умножения (*),  деления (/).

Соответствие типа результата от типов операндов

Особенности языка СИ

 Рассмотрим одну из особенностей на примере:
  int a,b;
  double c;
  a = 10;
  b = 4;
  c = a / b; // c будет равно 2, т.к выполняется операция не деления, а деления нацело или же:
  double x = 1 / 3; // x будет равен 0, по той же причине что и в предыдущем примере

Операции для целочисленных вычислений

 К операциям целочисленных вычислений относятся:
  операция взятия остатка от деления,
  побитовые операции,
  операции сдвигов,
  операции инкремента и декремента.
 Операция взятия остатка от деления(mod) является бинарной операцией и в языке СИ обозначается символом процента (%). Пример вычисления:
  int a = 10, b = 3, c;
  c = a % b; // с будет равно 1

Побитовые операции в СИ

 Побитовые операции языка СИ представлены тремя бинарными и одной унарной операцией. К бинарным побитовым операциям относятся:
  операция «И» (&),
  операция «ИЛИ» (|)
  операция «Исключающее ИЛИ» (^).

Вот таблица истинности для этих операций:

первый операнд второй операнд операция
и или исключающее или
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 1 0

Побитовые операции

Унарной побитовой операцией является операция отрицания, обозначаемая символом тильды (~). Пример:
  unsigned char a = 10, b; //a: 00001010 = 10
  b = ~a; //b: 11110101 = 245

Операции сдвига

Операции сдвига осуществляют побитовый сдвиг целого значения, указанного в первом операнде, вправо (символ >>) или влево (символ <<) на указанное во втором операнде целое число бит. Пример:
 unsigned char a = 10, b, c; //a: 00001010 = 10
 b = a << 2; //b: 00101000 = 40
 c = a >> 1; //c: 00000101 = 5

Операции инкремента и декремента

Операции инкремента (знак ++) и декремента (знак --) являются унарными и осуществляют увеличение и уменьшение целого значения на единицу соответственно.
 int a = 10, b, c;
 b = ++a //пред- инкремент b == 11
 c = a++; //пост- инкремент с == 11

 В современных языках программирования (в том числе и языке СИ стандарта С99) данные операции могут использоваться и для вещественных значений. Пример:
 double x = 12.5;
 x++;
 printf("%lf\n”,x); //вывод: 13.5

Операции отношения (сравнения)

В языках программирования операции отношения (сравнения) являются бинарными операциями, осуществляющими сравнение двух операндов и возвращающие результат сравнения в виде логического значения. В языке СИ принято логические значения ИСТИНА и ЛОЖЬ интерпретировать посредством целочисленных значений:
 0 – ЛОЖЬ, 1 – ИСТИНА.
Обозначение Название
> Больше
< Меньше
>= Больше или равно
<= Меньше или равно
== Равно
!= Не равно

Примеры
Несколько примеров использования операций сравнения:
 int a=5, b=4, c=10, x, y;
 x = a > b; //x == 1
 y = c == a; //y == 0

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

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

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


 Примеры логических операций:
  int a=1, b=0, c, d; //a – ИСТИНА, b – ЛОЖЬ
  c = a || b; //c == 1
  d = !b && a; //d == 1

Приоритеты операций

++, -- Операции пост- инкремента и декремента
() Вызов функции, группировка операций
Обращение к элементу массива
-> Обращение к полю структуры или объединения через указатель
. Обращение к полю структуры или объединения
++, -- Операции пред-инкремента и декремента
! Логическое «НЕ»
~ Бинарное отрицание(инверсия)
+, - Унарные плюс и минус
& Операция взятия адреса
* Разыменование указателя
sizeof Оператор определения размера
(type) Оператор преобразования типа
* Умножение
/ Деление
% Взятие остатка от деления
+ Сложение
- Вычитание
<<, >> Побитовые сдвиги влево и вправо
<, <=, >, >= Операции сравнения
==, != Операции сравнения
& Побитовое «И»
^ Побитовое «Исключающее ИЛИ»
| Побитовое «ИЛИ»
Логическое «И»
|| Логическое «ИЛИ»
?: Условная операция
= Оператор простого присвоения
*=, /=, %=, +=, -=, <<=, >>=, &=, ^=,|= Усовершенствованные операторы присвоения
, Запятая

Особенности трансляторов


 Не определяется порядок, в котором вычисляются аргументы функции при ее вызове. Поэтому следующий оператор может дать различные результаты при трансляции разными компиляторами:
  printf("%d %lf\n”, ++n, pow(2.0,n));
 Результат будет зависеть от того, получает ли n приращение до или после вызова функции pow. Чтобы решить проблему достаточно записать так:   n++;
  printf("%d %lf\n”, n,pow(2.0,n));

Схема автоматического приведения типа


 1.Если какой-либо из операторов имеет тип long double , то и другой приводится к long double .
 2.Иначе, если какой-либо из операторов имеет тип double , то и другой приводится к double .
 3.Иначе, если какой-либо из операторов имеет тип float , то и другой приводится к float .
 4.Иначе, для обоих операндов выполняется расширение целого типа; затем, если один из операндов имеет тип unsigned long int , то другой преобразуется в unsigned long int .
 5.Иначе, если один из операндов имеет тип long int , а другой – unsigned int , то результат зависит от того, представляет ли long int все значения unsigned int ; если это так, то операнд типа unsigned int
 6.приводится к типу long int ; если нет, то оба операнда преобразуются в unsigned long int .
 7.Иначе, если один из операндов имеет тип long int , то и другой приводится к long int .
 8.Иначе, оба операнда имеют тип int .

Оператор приведения типа

  int a = 15, b = 2; double r = 0.0;
  r = a / b; //r == 7.0

 Оператор приведения типа: (тип)выражение.
  r = (double)a / b; //Правильно
  r = (double) (a / b); //Неправильно

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


 В языке СИ присутствует так называемая условная операция, которая имеет следующий синтаксис:
  условие? выражение №1: выражение №2;
 Пример условной операции. Необходимо ввести с клавиатуры два вещественных значения и вывести на экран максимальное из этих значений:
  #include


  {
   double x,y;
   scanf("%lf %lf”,&x,&y);
   double max = (x > y) ? x: y;
   return 0;
  }

 Необходимо ввести с клавиатуры три вещественных значения и вывести на экран максимальное из этих значений:
  #include

Int main(int argc, char *argv)
  {
   double x, y, z;
   printf("Введите значения: ");
   scanf("%lf %lf %lf",&x,&y,&z);
   double max = (x > y) ? ((x > z) ? x: z): ((y > z) ? y:z);
   printf("Максимальное значение: %lf\n",max);
   return 0;
  }

 Вещественное число вводится с клавиатуры. Возвести число в четвертую степень, используя только две операции умножения.
  #include

Int main(int argc, char *argv)
  {
   double a;
   printf("Введите значение: ");
   scanf("%lf",&a);
   a *= (a *=a);
   printf("Результат: %lf\n",a);
   return 0;
  }

 Квадратное уравнение вида задается коэффициентами A, B и C. Определить какое количество корней имеет данное уравнение.
  #include

Int main(int argc, char *argv)
  {
   double a,b,c;
   printf("Введите коэффициенты A, B и С: ");
   scanf("%lf %lf %lf",&a,&b,&c);
   double d = b*b-4*a*c;
   int n = (d < 0.0)?0:(d > 0.0)?2:1;
   printf("Количество корней: %d\n",n);
   return 0;
  }

Последнее обновление: 19.06.2017

Отдельный набор операций представляет условные выражения. Такие операции возвращают логическое значение, то есть значение типа bool : true , если выражение истинно, и false , если выражение ложно. К подобным операциям относятся операции сравнения и логические операции.

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

В операциях сравнения сравниваются два операнда и возвращается значение типа bool - true , если выражение верно, и false , если выражение неверно.

    Сравнивает два операнда на равенство. Если они равны, то операция возвращает true , если не равны, то возвращается false :

    B; // false

    Сравнивает два операнда и возвращает true, если операнды не равны, и false, если они равны.

    Int a = 10; int b = 4; bool c = a != b; // true bool d = a!=10; // false

    Операция "меньше чем". Возвращает true, если первый операнд меньше второго, и false, если первый операнд больше второго:

    Int a = 10; int b = 4; bool c = a < b; // false

    Операция "больше чем". Сравнивает два операнда и возвращает true, если первый операнд больше второго, иначе возвращает false:

    Int a = 10; int b = 4; bool c = a > b; // true bool d = a > 25; // false

    Операция "меньше или равно". Сравнивает два операнда и возвращает true, если первый операнд меньше или равен второму. Иначе возвращает false.

    Int a = 10; int b = 4; bool c = a <= b; // false bool d = a <= 25; // true

    Операция "больше или равно". Сравнивает два операнда и возвращает true, если первый операнд больше или равен второму, иначе возвращается false:

    Int a = 10; int b = 4; bool c = a >= b; // true bool d = a >= 25; // false

Операции <, > <=, >= имеют больший приоритет, чем == и!=.

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

Также в C# определены логические операторы, которые также возвращают значение типа bool . В качестве операндов они принимают значения типа bool . Как правило, применяются к отношениям и объединяют несколько операций сравнения.

    Операция логического сложения или логическое ИЛИ. Возвращает true, если хотя бы один из операндов возвращает true.

    Bool x1 = (5 > 6) | (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x2 = (5 > 6) | (4 > 6); // 5 > 6 - false, 4 >

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

    Bool x1 = (5 > 6) & (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается false bool x2 = (5 < 6) & (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true

    Операция логического сложения. Возвращает true, если хотя бы один из операндов возвращает true.

    Bool x1 = (5 > 6) || (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x2 = (5 > 6) || (4 > 6); // 5 > 6 - false, 4 > 6 - false, поэтому возвращается false

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

    Bool x1 = (5 > 6) && (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается false bool x2 = (5 < 6) && (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true

    Операция логического отрицания. Производится над одним операндом и возвращает true, если операнд равен false. Если операнд равен true, то операция возвращает false:

    Bool a = true; bool b = !a; // false

    Операция исключающего ИЛИ. Возвращает true, если либо первый, либо второй операнд (но не одновременно) равны true, иначе возвращает false

    Bool x5 = (5 > 6) ^ (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x6 = (50 > 6) ^ (4 / 2 < 3); // 50 > 6 - true, 4/2 < 3 - true, поэтому возвращается false

Здесь у нас две пары операций | и || (а также & и &&) выполняют похожие действия, однако же они не равнозначны.

В выражении z=x|y; будут вычисляться оба значения - x и y.

В выражении же z=x||y; сначала будет вычисляться значение x, и если оно равно true , то вычисление значения y уже смысла не имеет, так как у нас в любом случае уже z будет равно true . Значение y будет вычисляться только в том случае, если x равно false

То же самое касается пары операций &/&& . В выражении z=x&y; будут вычисляться оба значения - x и y.

В выражении же z=x&&y; сначала будет вычисляться значение x, и если оно равно false , то вычисление значения y уже смысла не имеет, так как у нас в любом случае уже z будет равно false . Значение y будет вычисляться только в том случае, если x равно true

Поэтому операции || и && более удобны в вычислениях, так как позволяют сократить время на вычисление значения выражения, и тем самым повышают производительность. А операции | и & больше подходят для выполнения поразрядных операций над числами.

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

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

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

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

Результатом выполнения оператора отношения или логического оператора является логическое значение типа 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), то ее результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода .

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

Теги: Си логические операторы, логическое отрицание, логическое НЕ, !, логическое ИЛИ, логическое сложение, 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

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