Операторы в C: полное руководство по арифметическим, битовым, логическим и другим операторам
Классификация операторов
Операторы в C делятся на категории по функции и количеству операндов:
- Унарные — 1 операнд (
++,--,!,~,+,-,*(разыменование),&(адрес),sizeof). - Бинарные — 2 операнда (арифметические, сравнения, логические, битовые, присваивания).
- Тернарный — 3 операнда (
?:).
Арифметические операторы
Предположим int a = 10, b = 20;
| Оператор | Имя | Пример | Результат |
|---|---|---|---|
+ | Сложение | a + b | 30 |
- | Вычитание | a - b | -10 |
* | Умножение | a * b | 200 |
/ | Деление | b / a | 2 (целочисленное!) |
% | Остаток от деления | b % a | 0 |
++ | Инкремент | ++a (префикс) / a++ (постфикс) | 11 / 10 (значение выражения) |
-- | Декремент | --a / a-- | 9 / 10 |
Важно: целочисленное деление отбрасывает дробную часть. 5 / 2 == 2. Для дробного — приведите к float: (float)a / b.
Операторы присваивания
| Оператор | Эквивалент | Пример |
|---|---|---|
= | c = a + b | Присваивание |
+= | c = c + a | Сложение с присваиванием |
-= | c = c - a | Вычитание с присваиванием |
*= | c = c * a | Умножение с присваиванием |
/= | c = c / a | Деление с присваиванием |
%= | c = c % a | Остаток с присваиванием |
<<= | c = c << 2 | Сдвиг влево с присваиванием |
>>= | c = c >> 2 | Сдвиг вправо с присваиванием |
&= | c = c & 2 | Побитовое И с присваиванием |
^= | c = c ^ 2 | Побитовое XOR с присваиванием |
|= | c = c | 2 | Побитовое ИЛИ с присваиванием |
Операторы отношения (сравнения)
Возвращают int: 1 (истина) или 0 (ложь). a=10, b=20:
| Оператор | Смысл | Пример | Результат |
|---|---|---|---|
== | Равно | a == b | 0 |
!= | Не равно | a != b | 1 |
> | Больше | a > b | 0 |
< | Меньше | a < b | 1 |
>= | Больше или равно | a >= b | 0 |
<= | Меньше или равно | a <= b | 1 |
Логические операторы
Операнды: 0 = ложь, не-0 = истина. Результат: 1 или 0. Короткое замыкание (short-circuit) — второй операнд не вычисляется, если результат определён первым.
| Оператор | Имя | Пример (a=1, b=0) | Результат |
|---|---|---|---|
&& | Логическое И | a && b | 0 |
|| | Логическое ИЛИ | a || b | 1 |
! | Логическое НЕ | !a | 0 |
Пример короткого замыкания:
if (ptr != NULL && ptr->len > 0) // ptr->len не вычислится, если ptr == NULL
if (file = fopen(...)) { ... } // присваивание В условии — идиома
Битовые операторы
Работают с отдельными битами целых чисел. a = 60 (0011 1100), b = 13 (0000 1101):
| Оператор | Имя | Пример | Результат (bin) | Результат (dec) |
|---|---|---|---|---|
& | Побитовое И (AND) | a & b | 0000 1100 | 12 |
| | Побитовое ИЛИ (OR) | a | b | 0011 1101 | 61 |
^ | Побитовое XOR (искл. ИЛИ) | a ^ b | 0011 0001 | 49 |
~ | Побитовое НЕ (NOT, унарный) | ~a | 1100 0011 | -61 (дополнение до 2) |
<< | Сдвиг влево | a << 2 | 1111 0000 | 240 |
>> | Сдвиг вправо | a >> 2 | 0000 1111 | 15 |
Важно: сдвиг отрицательных чисел — implementation-defined (обычно арифметический сдвиг с сохранением знака). Сдвиг на ≥ ширину типа — UB.
Разные важные операторы
| Оператор | Имя | Описание | Пример |
|---|---|---|---|
sizeof | Размер типа/выражения | Возвращает size_t (байты). Вычисляется на этапе компиляции (кроме VLA). | sizeof(int), sizeof x |
& | Взятие адреса | Унарный. Возвращает указатель на объект. | &x |
* | Разыменование | Унарный. Доступ к значению по адресу. | *ptr |
?: | Тернарный (условный) | cond ? expr1 : expr2. Если cond истинно → expr1, иначе expr2. | max = (a > b) ? a : b; |
, | Запятая | Вычисляет слева направо, значение — последнее выражение. | for (i=0, j=10; i<j; i++, j--) |
. -> | Доступ к члену | Структура / указатель на структуру. | s.member, p->member |
[] | Индексация | arr[i] ≡ *(arr + i). | arr[5] |
(type) | Приведение типа (cast) | Явное преобразование. | (float)a / b |
Приоритет и ассоциативность
Выше в таблице — выше приоритет. Операторы одного приоритета группируются по ассоциативности.
| Приоритет | Операторы | Ассоциативность |
|---|---|---|
| 1 (высший) | () [] . -> ++ -- (постфикс) | ← |
| 2 | ++ -- + - ! ~ (type) * & sizeof (унарные) | → |
| 3 | * / % | ← |
| 4 | + - | ← |
| 5 | << >> | ← |
| 6 | < <= > >= | ← |
| 7 | == != | ← |
| 8 | & | ← |
| 9 | ^ | ← |
| 10 | | | ← |
| 11 | && | ← |
| 12 | || | ← |
| 13 | ?: | → |
| 14 | = += -= *= /= %= <<= >>= &= ^= |= | → |
| 15 (низший) | , | ← |
Примеры приоритета
x = 7 + 3 * 2; // * выше + → x = 7 + 6 = 13
x = (7 + 3) * 2; // скобки меняют порядок → x = 20
a = b = c = 0; // = правоассоциативен → a = (b = (c = 0))
*p++ // постфикс ++ выше * → *(p++) — разыменовать, потом инкремент указателя
(*p)++ // скобки: (*p)++ — инкремент значения
Приведение типов (type conversions)
- Неявное (usual arithmetic conversions): целое → float, narrow → wide, signed ↔ unsigned (правила ранга).
- Явное (cast):
(type)expr. Используйте осторожно — может терять данные/знак.
Undefined Behavior (UB) с операторами
- Деление на ноль:
a / 0. - Сдвиг на отрицательное или ≥ ширины:
a << -1,a >> 32(для 32-бит). - Переполнение знакового целого:
INT_MAX + 1. - Множественное изменение без точки следования:
i = i++,a[i] = i++(до C11). - Разыменование NULL/висячего указателя.
Санитайзеры (-fsanitize=undefined) помогают ловить UB в runtime.
Язык C
- Операторы C# — исчерпывающее руководство по операторам в C#
- Освоение побитовых и сдвиговых операторов в C#: полное руководство
- Освоение операторов C++: полное руководство с практическими примерами
- Операторы в C: исчерпывающее руководство
- Мастерство операторов Python: Полное руководство
- Освоение операторов Java: типы, синтаксис и практические примеры
- Побитовые операторы в C: И, ИЛИ, XOR, сдвиги и дополнение — подробно
- Операторы Verilog: основная арифметика и управление для синтеза
- Основные операторы Java: полное руководство
- Полное руководство по операторам C++: типы, использование и лучшие практики