Язык C: операторы

Предыдущая статья: “Язык C: классы памяти

Оператор — это символ, который дает команду компилятору выполнить определенные математические или логические функции. В распоряжении пользователей языка С множество встроенных операторов различных типов:

  • Арифметические операторы.
  • Операторы сравнения.
  • Логические операторы.
  • Побитовые операторы.
  • Операторы присваивания.
  • Другие операторы.

Рассмотрим принцип работы каждого типа операторов.

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

Предположим, что переменная A содержит значение 10, а переменная B содержит значение 20.

  1. Сложение (+) складывает два операнда: A + B = 30.
  2. Вычитание () вычитает второй операнд из первого: A — B = -10.
  3. Умножение (*) перемножает оба операнда: A * B = 200.
  4. Деление (/) делит числитель на знаменатель: B / A = 2.
  5. Модуль (%) определяет остаток после деления целых чисел: B % A = 0.
  6. Инкремент (++) увеличивает целочисленное значение на единицу: A++ = 11.
  7. Декремент ( — ), уменьшающий целочисленное значение на единицу: A — = 9.

Примеры написания кода с арифметическими операторами

#include <stdio.h>

main() {
   int a = 21;
   int b = 10;
   int c ;

   c = a + b;
   printf("Line 1 - Value of c is %d\n", c );
	
   c = a - b;
   printf("Line 2 - Value of c is %d\n", c );
	
   c = a * b;
   printf("Line 3 - Value of c is %d\n", c );
	
   c = a / b;
   printf("Line 4 - Value of c is %d\n", c );
	
   c = a % b;
   printf("Line 5 - Value of c is %d\n", c );
	
   c = a++; 
   printf("Line 6 - Value of c is %d\n", c );
	
   c = a--; 
   printf("Line 7 - Value of c is %d\n", c );
}

Результат:

Line 1 - Value of c is 31
Line 2 - Value of c is 11
Line 3 - Value of c is 210
Line 4 - Value of c is 2
Line 5 - Value of c is 1
Line 6 - Value of c is 21
Line 7 - Value of c is 22

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

Предположим, что переменная A содержит значение 10, а переменная B содержит значение 20.

  1. Равенство (==) проверяет, равны или нет значения двух операндов. Если да, то условие становится истинным: (A == B) не является истинным.
  2. Неравенство (!=) проверяет, равны или нет значения двух операндов. Если значения не равны, то условие становится истинным: (A != B) — истинно.
  3. Больше (>) проверяет, больше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным: (A > B) не является истинным.
  4. Меньше (<) проверяет, меньше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным: (A < B) — истинно.
  5. Больше или равно (>=) проверяет, действительно ли значение левого операнда больше или равно значению правого операнда. Если да, то условие становится истинным: (A >= B) не является истинным.
  6. Меньше или равно (<=) проверяет, действительно ли значение левого операнда меньше или равно значению правого операнда. Если да, то условие становится истинным: (A <= B) — истинно.

Примеры написания кода с операторами сравнения

#include <stdio.h>

main() {
   int a = 21;
   int b = 10;
   int c ;

   if( a == b ) {
      printf("Line 1 - a is equal to b\n" );
   } else {
      printf("Line 1 - a is not equal to b\n" );
   }
	
   if ( a < b ) {
      printf("Line 2 - a is less than b\n" );
   } else {
      printf("Line 2 - a is not less than b\n" );
   }
	
   if ( a > b ) {
      printf("Line 3 - a is greater than b\n" );
   } else {
      printf("Line 3 - a is not greater than b\n" );
   }
   
   /* Изменим значения a и b */
   a = 5;
   b = 20;
	
   if ( a <= b ) {
      printf("Line 4 - a is either less than or equal to  b\n" );
   }
	
   if ( b >= a ) {
      printf("Line 5 - b is either greater than  or equal to b\n" );
   }
}

Результат:

Line 1 - a is not equal to b
Line 2 - a is not less than b
Line 3 - a is greater than b
Line 4 - a is either less than or equal to b
Line 5 - b is either greater than or equal to b

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

Предположим, что переменная A равна 1, а переменная B равна 0.

  1. Логический оператор AND (&&). Если оба операнда ненулевые, то условие становится истинным: (A && B) — ложно.
  2. Логический оператор OR (||). Если любой из двух операндов ненулевой, то условие становится истинным: (A || B) — истинно.
  3. Логический оператор NOT(!). Используется для преобразования в обратное логическое состояние своего операнда. Если условие истинно, то оператор NOT сделает его ложным: !(A && B) — истинно.

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

#include <stdio.h>

main() {
   int a = 5;
   int b = 20;
   int c ;

   if ( a && b ) {
      printf("Line 1 - Condition is true\n" );
   }
	
   if ( a || b ) {
      printf("Line 2 - Condition is true\n" );
   }
   
   /* изменим значения a и b */
   a = 0;
   b = 10;
	
   if ( a && b ) {
      printf("Line 3 - Condition is true\n" );
   } else {
      printf("Line 3 - Condition is not true\n" );
   }
	
   if ( !(a && b) ) {
      printf("Line 4 - Condition is true\n" );
   }
	
}

Результат:

Line 1 - Condition is true
Line 2 - Condition is true
Line 3 - Condition is not true
Line 4 - Condition is true

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

Побитовый оператор работает с битами и выполняет побитовую операцию. Таблицы истинности для &, | и ^ выглядят следующим образом:

Если предположить, что A = 60 и B = 13 в бинарном формате, то они будут выглядеть следующим образом:

A = 0011 1100

B = 0000 1101

 — — — — — — — — —

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

Ниже перечислены побитовые операторы, поддерживаемые C. Предположим, что переменная ‘A’ содержит значение 60, а переменная ‘B’ — значение 13.

  1. Побитовый оператор AND (&) копирует бит в результат, если он есть в обоих операндах: (A & B) = 12, т. е. 0000 1100.
  2. Побитовый оператор OR (|) копирует бит, если он есть в любом из операндов: (A | B) = 61, т. е. 0011 1101.
  3. Побитовый оператор XOR (^) копирует бит, если он установлен в одном операнде, но не в обоих: (A ^ B) = 49, т. е. 0011 0001.
  4. Оператор дополнения бинарной единицы (~), являясь унарным, обладает эффектом инвертирования битов: (~A ) = ~(60), т. е. -0111101.
  5. Побитовый оператор сдвига влево (<<) сдвигает значение левого операнда влево на количество битов, указанное правым операндом: A << 2 = 240, т. е. 1111 0000.
  6. Побитовый оператор сдвига вправо (>>) сдвигает значение левого операнда вправо на количество битов, указанное правым операндом: A >> 2 = 15, т. е. 0000 1111.

Примеры написания кода с бинарными операторами

#include <stdio.h>

main() {
   unsigned int a = 60;	/* 60 = 0011 1100 */  
   unsigned int b = 13;	/* 13 = 0000 1101 */
   int c = 0;    

   c = a & b;       /* 12 = 0000 1100 */ 
   printf("Line 1 - Value of c is %d\n", c );  

   c = a | b;       /* 61 = 0011 1101 */
   printf("Line 2 - Value of c is %d\n", c );

   c = a ^ b;       /* 49 = 0011 0001 */
   printf("Line 3 - Value of c is %d\n", c );

   c = ~a;          /*-61 = 1100 0011 */
   printf("Line 4 - Value of c is %d\n", c );

   c = a << 2;     /* 240 = 1111 0000 */
   printf("Line 5 - Value of c is %d\n", c );

   c = a >> 2;     /* 15 = 0000 1111 */
   printf("Line 6 - Value of c is %d\n", c );
}

Результат:

Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15

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

  1. Простой оператор присваивания (=) присваивает значения правых операндов левому операнду: C = A + B с присвоением A + B операнду C.
  2. Add AND (+=) добавляет правый операнд к левому операнду и присваивает результат левому операнду: C += A эквивалентно C = C + A.
  3. Subtract AND (-=) вычитает правый операнд из левого операнда и присваивает результат левому операнду: C -= A эквивалентно C = C-A.
  4. Multiply AND (*=) перемножает правый операнд с левым операндом и присваивает результат левому операнду: C *= A эквивалентен C = C * A.
  5. Divide AND (/=) делит левый операнд на правый операнд и присваивает результат левому операнду: C /= A эквивалентен C = C / A
  6. Modulus AND (%=) вычисляет остаток от деления двух операндов и присваивает результат левому операнду: C %= A эквивалентно C = C % A.
  7. Left shift AND (<<=) — побитовый сдвиг влево, совмещенный с операцией присваивания: C <<= 2 эквивалентно C = C << 2.
  8. Right shift AND (>>=) — побитовый сдвиг вправо, совмещенный с операцией присваивания: C >>= 2 эквивалентно C = C >> 2.
  9. Bitwise AND (&=) — побитовое “И”, совмещенное с операцией присваивания: C &= 2 то же самое, что C = C & 2.
  10. Bitwise XOR (^=) — побитовое “исключающее ИЛИ”, совмещенное с операцией присваивания: C ^= 2 то же самое, что C = C ^ 2.
  11. Bitwise OR (|=) — побитовое “ИЛИ”, совмещенное с операцией присваивания: C |= 2 то же самое, что C = C | 2.

Примеры написания кода с операторами присваивания

#include <stdio.h>

main() {
   int a = 21;
   int c ;

   c =  a;
   printf("Line 1 - =  Operator Example, Value of c = %d\n", c );

   c +=  a;
   printf("Line 2 - += Operator Example, Value of c = %d\n", c );

   c -=  a;
   printf("Line 3 - -= Operator Example, Value of c = %d\n", c );

   c *=  a;
   printf("Line 4 - *= Operator Example, Value of c = %d\n", c );

   c /=  a;
   printf("Line 5 - /= Operator Example, Value of c = %d\n", c );

   c  = 200;
   c %=  a;
   printf("Line 6 - %= Operator Example, Value of c = %d\n", c );

   c <<=  2;
   printf("Line 7 - <<= Operator Example, Value of c = %d\n", c );

   c >>=  2;
   printf("Line 8 - >>= Operator Example, Value of c = %d\n", c );

   c &=  2;
   printf("Line 9 - &= Operator Example, Value of c = %d\n", c );

   c ^=  2;
   printf("Line 10 - ^= Operator Example, Value of c = %d\n", c );

   c |=  2;
   printf("Line 11 - |= Operator Example, Value of c = %d\n", c );
}

Результат:

Line 1 - =  Operator Example, Value of c = 21
Line 2 - += Operator Example, Value of c = 42
Line 3 - -= Operator Example, Value of c = 21
Line 4 - *= Operator Example, Value of c = 441
Line 5 - /= Operator Example, Value of c = 21
Line 6 - %= Operator Example, Value of c = 11
Line 7 - <<= Operator Example, Value of c = 44
Line 8 - >>= Operator Example, Value of c = 11
Line 9 - &= Operator Example, Value of c = 2
Line 10 - ^= Operator Example, Value of c = 0
Line 11 - |= Operator Example, Value of c = 2

Другие операторы

Помимо рассмотренных выше в языке C есть еще несколько важных операторов:

  1. Оператор размера sizeof() возвращает размер переменной, например: sizeof(a), где a — целое число, возвращает 4.
  2. Оператор ссылки (&) возвращает фактический адрес переменной, например: &a.
  3. Оператор непрямого обращения (*) обращает к объекту, на который указывает переменная, например: *a;
  4. Тернарный условный оператор (? 🙂 выполняет тернарную условную операцию: если условие ? истинно, тогда значение X : иначе значение Y.

Примеры написания кода с операторами sizeof(), &, *, ?

#include <stdio.h>

main() {
   int a = 4;
   short b;
   double c;
   int* ptr;

   /* пример оператора sizeof */
   printf("Line 1 - Size of variable a = %d\n", sizeof(a) );
   printf("Line 2 - Size of variable b = %d\n", sizeof(b) );
   printf("Line 3 - Size of variable c= %d\n", sizeof(c) );

   /* примеры операторов & и * */
   ptr = &a;	/* 'ptr' now contains the address of 'a'*/
   printf("value of a is  %d\n", a);
   printf("*ptr is %d.\n", *ptr);

   /* пример тернарного оператора */
   a = 10;
   b = (a == 1) ? 20: 30;
   printf( "Value of b is %d\n", b );

   b = (a == 10) ? 20: 30;
   printf( "Value of b is %d\n", b );
}

Результат:

Line 1 - Size of variable a = 4
Line 2 - Size of variable b = 2
Line 3 - Size of variable c= 8
value of a is 4
*ptr is 4.
Value of b is 30
Value of b is 20

Старшинство операторов

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

Рассмотрим конкретный пример: x = 7 + 3 * 2. Здесь x присваивается 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому сначала выполняется умножение 3*2, а затем результат складывается с 7. Таким образом, операторы с более высоким старшинством должны оцениваться первыми.

В приведенном ниже списке операторы с наибольшим старшинством находятся в самом верху, а с наименьшим — внизу. В скобках указана ассоциативность операторов.

Примеры написания кода с соблюдением старшинства операторов

#include <stdio.h>

main() {
   int a = 20;
   int b = 10;
   int c = 15;
   int d = 5;
   int e;
 
   e = (a + b) * c / d;      // ( 30 * 15 ) / 5
   printf("Value of (a + b) * c / d is : %d\n",  e );

   e = ((a + b) * c) / d;    // (30 * 15 ) / 5
   printf("Value of ((a + b) * c) / d is  : %d\n" ,  e );

   e = (a + b) * (c / d);   // (30) * (15/5)
   printf("Value of (a + b) * (c / d) is  : %d\n",  e );

   e = a + (b * c) / d;     //  20 + (150/5)
   printf("Value of a + (b * c) / d is  : %d\n" ,  e );
  
   return 0;
}

Результат:

Value of (a + b) * c / d is : 90
Value of ((a + b) * c) / d is : 90
Value of (a + b) * (c / d) is : 90
Value of a + (b * c) / d is : 50

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен

Предыдущая статьяЧетыре метода, которые повысят качество работы с Pandas
Следующая статья6 лайфхаков для улучшения кода JavaScript