Операторы Zig
Операторы и выражения — это фундаментальные компоненты языков программирования, используемые для выполнения различных операций.
В Zig операторы можно разделить на несколько категорий, включая арифметические операторы, операторы сравнения, логические операторы, побитовые операторы, операторы присваивания и другие операторы.
Ниже приведены подробные описания и примеры для каждого типа оператора.
Арифметические операторы
| Operator | Описание |
|---|---|
| + | Сложение |
| - | Вычитание |
| * | Умножение |
| / | Деление |
| % | Остаток (операция по модулю) |
Пример
const std = @import("std");
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const add: i32 = a + b;
const subtract: i32 = a - b;
const multiply: i32 = a * b;
const divide: i32 = a / b;
const remainder: i32 = a % b;
std.debug.print("a + b = {}\n", .{add});
std.debug.print("a - b = {}\n", .{subtract});
std.debug.print("a * b = {}\n", .{multiply});
std.debug.print("a / b = {}\n", .{divide});
std.debug.print("a % b = {}\n", .{remainder});
}
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const add: i32 = a + b;
const subtract: i32 = a - b;
const multiply: i32 = a * b;
const divide: i32 = a / b;
const remainder: i32 = a % b;
std.debug.print("a + b = {}\n", .{add});
std.debug.print("a - b = {}\n", .{subtract});
std.debug.print("a * b = {}\n", .{multiply});
std.debug.print("a / b = {}\n", .{divide});
std.debug.print("a % b = {}\n", .{remainder});
}
Скомпилированный вывод:
a + b = 8 a - b = 2 a * b = 15 a / b = 1 a % b = 2
Операторы отношения
| Operator | Описание |
|---|---|
| == | Равно |
| != | Не равно |
| > | Больше |
| < | Меньше |
| >= | Больше или равно |
| <= | Меньше или равно |
Пример
const std = @import("std");
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const equal: bool = a == b;
const not_equal: bool = a != b;
const greater: bool = a > b;
const less: bool = a < b;
const greater_equal: bool = a >= b;
const less_equal: bool = a <= b;
std.debug.print("a == b: {}\n", .{equal});
std.debug.print("a != b: {}\n", .{not_equal});
std.debug.print("a > b: {}\n", .{greater});
std.debug.print("a < b: {}\n", .{less});
std.debug.print("a >= b: {}\n", .{greater_equal});
std.debug.print("a <= b: {}\n", .{less_equal});
}
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const equal: bool = a == b;
const not_equal: bool = a != b;
const greater: bool = a > b;
const less: bool = a < b;
const greater_equal: bool = a >= b;
const less_equal: bool = a <= b;
std.debug.print("a == b: {}\n", .{equal});
std.debug.print("a != b: {}\n", .{not_equal});
std.debug.print("a > b: {}\n", .{greater});
std.debug.print("a < b: {}\n", .{less});
std.debug.print("a >= b: {}\n", .{greater_equal});
std.debug.print("a <= b: {}\n", .{less_equal});
}
Скомпилированный вывод:
a == b: false a != b: true a > b: true a < b: false a >= b: true a <= b: false
Логические операторы
| Operator | Описание |
|---|---|
| и | Логическое И |
| или | Логическое ИЛИ |
| ! | Логическое НЕ |
Пример
const std = @import("std");
pub fn main() void {
const a: bool = true;
const b: bool = false;
const and_result: bool = a and b;
const or_result: bool = a or b;
const not_result: bool = !a;
std.debug.print("a and b: {}\n", .{and_result}); // false
std.debug.print("a or b: {}\n", .{or_result}); // true
std.debug.print("!a: {}\n", .{not_result}); // false
}
pub fn main() void {
const a: bool = true;
const b: bool = false;
const and_result: bool = a and b;
const or_result: bool = a or b;
const not_result: bool = !a;
std.debug.print("a and b: {}\n", .{and_result}); // false
std.debug.print("a or b: {}\n", .{or_result}); // true
std.debug.print("!a: {}\n", .{not_result}); // false
}
Скомпилированный вывод:
a and b: false a or b: true !a: false
Побитовые операторы
| Operator | Описание |
|---|---|
| & | Побитовое И |
| | | Побитовое ИЛИ |
| ^ | Побитовое XOR |
| ~ | Побитовое НЕ |
| << | Сдвиг влево |
| >> | Сдвиг вправо |
Пример
const std = @import("std");
pub fn main() void {
const a: i32 = 5; // 0101
const b: i32 = 3; // 0011
const bit_and: i32 = a & b; // 0001
const bit_or: i32 = a | b; // 0111
const bit_xor: i32 = a ^ b; // 0110
const bit_not: i32 = ~a; // 11111111111111111111111111111010
const left_shift: i32 = a << 1; // 1010
const right_shift: i32 = a >> 1; // 0010
std.debug.print("a & b: {}\n", .{bit_and});
std.debug.print("a | b: {}\n", .{bit_or});
std.debug.print("a ^ b: {}\n", .{bit_xor});
std.debug.print("~a: {}\n", .{bit_not});
std.debug.print("a << 1: {}\n", .{left_shift});
std.debug.print("a >> 1: {}\n", .{right_shift});
}
pub fn main() void {
const a: i32 = 5; // 0101
const b: i32 = 3; // 0011
const bit_and: i32 = a & b; // 0001
const bit_or: i32 = a | b; // 0111
const bit_xor: i32 = a ^ b; // 0110
const bit_not: i32 = ~a; // 11111111111111111111111111111010
const left_shift: i32 = a << 1; // 1010
const right_shift: i32 = a >> 1; // 0010
std.debug.print("a & b: {}\n", .{bit_and});
std.debug.print("a | b: {}\n", .{bit_or});
std.debug.print("a ^ b: {}\n", .{bit_xor});
std.debug.print("~a: {}\n", .{bit_not});
std.debug.print("a << 1: {}\n", .{left_shift});
std.debug.print("a >> 1: {}\n", .{right_shift});
}
Скомпилированный вывод:
a & b: 1 a | b: 7 a ^ b: 6 ~a: -6 a << 1: 10 a >> 1: 2
Операторы присваивания
| Operator | Описание |
|---|---|
| = | Присваивание |
| += | Присваивание со сложением |
| -= | Присваивание с вычитанием |
| *= | Присваивание с умножением |
| /= | Присваивание с делением |
| %= | Присваивание с остатком |
| &= | Присваивание с побитовым И |
| |= | Присваивание с побитовым ИЛИ |
| ^= | Присваивание с побитовым исключающим ИЛИ |
| <<= | Присваивание сдвига влево |
| >>= | Присваивание сдвига вправо |
Пример
const std = @import("std");
pub fn main() void {
var a: i32 = 5;
const b: i32 = 3;
a += b; // эквивалентно a = a + b;
std.debug.print("a += b: {}\n", .{a});
a -= b; // эквивалентно a = a - b;
std.debug.print("a -= b: {}\n", .{a});
a *= b; // эквивалентно a = a * b;
std.debug.print("a *= b: {}\n", .{a});
a = @divTrunc(a, b); // эквивалентно a = a / b;
std.debug.print("a /= b: {}\n", .{a});
a = @mod(a, b); // эквивалентно a = a % b;
std.debug.print("a %= b: {}\n", .{a});
a &= b; // эквивалентно a = a & b;
std.debug.print("a &= b: {}\n", .{a});
a |= b; // эквивалентно a = a | b;
std.debug.print("a |= b: {}\n", .{a});
a ^= b; // эквивалентно a = a ^ b;
std.debug.print("a ^= b: {}\n", .{a});
a <<= 1; // эквивалентно a = a << 1;
std.debug.print("a <<= 1: {}\n", .{a});
a >>= 1; // эквивалентно a = a >> 1;
std.debug.print("a >>= 1: {}\n", .{a});
}
pub fn main() void {
var a: i32 = 5;
const b: i32 = 3;
a += b; // эквивалентно a = a + b;
std.debug.print("a += b: {}\n", .{a});
a -= b; // эквивалентно a = a - b;
std.debug.print("a -= b: {}\n", .{a});
a *= b; // эквивалентно a = a * b;
std.debug.print("a *= b: {}\n", .{a});
a = @divTrunc(a, b); // эквивалентно a = a / b;
std.debug.print("a /= b: {}\n", .{a});
a = @mod(a, b); // эквивалентно a = a % b;
std.debug.print("a %= b: {}\n", .{a});
a &= b; // эквивалентно a = a & b;
std.debug.print("a &= b: {}\n", .{a});
a |= b; // эквивалентно a = a | b;
std.debug.print("a |= b: {}\n", .{a});
a ^= b; // эквивалентно a = a ^ b;
std.debug.print("a ^= b: {}\n", .{a});
a <<= 1; // эквивалентно a = a << 1;
std.debug.print("a <<= 1: {}\n", .{a});
a >>= 1; // эквивалентно a = a >> 1;
std.debug.print("a >>= 1: {}\n", .{a});
}
Скомпилированный вывод:
a += b: 8 a -= b: 5 a *= b: 15 a /= b: 5 a %= b: 2 a &= b: 2 a |= b: 3 a ^= b: 0 a <<= 1: 0 a >>= 1: 0
Другие операторы
| Operator | Описание |
|---|---|
| ++ | Инкремент |
| -- | Декремент |
Пример
const std = @import("std");
pub fn main() void {
var a: i32 = 5;
a += 1; // В Zig отсутствует оператор ++, вместо него используйте += 1
std.debug.print("a += 1: {}\n", .{a});
a -= 1; // В Zig отсутствует оператор --, вместо него используйте -= 1
std.debug.print("a -= 1: {}\n", .{a});
}
pub fn main() void {
var a: i32 = 5;
a += 1; // В Zig отсутствует оператор ++, вместо него используйте += 1
std.debug.print("a += 1: {}\n", .{a});
a -= 1; // В Zig отсутствует оператор --, вместо него используйте -= 1
std.debug.print("a -= 1: {}\n", .{a});
}
Скомпилированный вывод:
a += 1: 6 a -= 1: 5
Приоритет операторов
Ниже приведён список приоритетов операторов Zig, упорядоченный от высшего к низшему:
| Приоритет | Operator | Описание |
|---|---|---|
| 1 | [] | Операция индексации, доступ к массиву или указателю |
| 1 | . | Доступ к члену |
| 2 | fn_call() | Вызов функции |
| 2 | @builtin() | Вызов встроенной функции |
| 3 | ! | Распространение ошибок |
| 3 | ? | Разворачивание опционального значения |
| 4 | * & | Разыменование указателя и операции взятия адреса |
| 5 | + - | Унарные плюс и минус |
| 6 | ~ | Побитовое НЕ |
| 7 | * / % | Умножение, деление, остаток |
| 8 | + - | Сложение, вычитание |
| 9 | << >> | Побитовый сдвиг влево, сдвиг вправо |
| 10 | & | Побитовое И |
| 11 | ^ | Побитовое XOR |
| 12 | ` | ` |
| 13 | == != | Равно, не равно |
| 13 | < <= > >= | Меньше, меньше или равно, больше, больше или равно |
| 14 | and | Логическое И |
| 15 | or | Логическое ИЛИ |
| 16 | orelse | Или иначе вернуть другое значение |
| 17 | catch | Захват ошибки |
| 18 | = | Присваивание |
| 19 | -> | Тело функции-замыкания или обозначение типа возвращаемого значения |
Примечания:
- Ассоциативность: Обычно операторы Zig являются левоассоциативными, но вы можете обратиться к документации в зависимости от конкретной функции оператора.
- Примечания: Операторы в Zig спроектированы простыми и понятными, они избегают сложных неявных моделей поведения, встречающихся во многих языках, например отсутствия неявного преобразования типов.
Следующий пример показывает, как приоритет операторов влияет на порядок вычисления выражений:
Пример
const std = @import("std");
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const c: i32 = 2;
// Умножение имеет более высокий приоритет, чем сложение
const result1: i32 = a + b * c; // 5 + (3 * 2) = 11
std.debug.print("a + b * c = {}\n", .{result1});
// Используйте круглые скобки для изменения приоритета
const result2: i32 = (a + b) * c; // (5 + 3) * 2 = 16
std.debug.print("(a + b) * c = {}\n", .{result2});
// Операторы сравнения имеют более высокий приоритет, чем логические операторы
const result3: bool = a > b and b > c; // (5 > 3) and (3 > 2) = true
std.debug.print("a > b and b > c = {}\n", .{result3});
// Логическое НЕ имеет более высокий приоритет, чем логическое И
const result4: bool = !(a > b) and b > c; // !(5 > 3) and (3 > 2) = false
std.debug.print("!(a > b) and b > c = {}\n", .{result4});
}
pub fn main() void {
const a: i32 = 5;
const b: i32 = 3;
const c: i32 = 2;
// Умножение имеет более высокий приоритет, чем сложение
const result1: i32 = a + b * c; // 5 + (3 * 2) = 11
std.debug.print("a + b * c = {}\n", .{result1});
// Используйте круглые скобки для изменения приоритета
const result2: i32 = (a + b) * c; // (5 + 3) * 2 = 16
std.debug.print("(a + b) * c = {}\n", .{result2});
// Операторы сравнения имеют более высокий приоритет, чем логические операторы
const result3: bool = a > b and b > c; // (5 > 3) and (3 > 2) = true
std.debug.print("a > b and b > c = {}\n", .{result3});
// Логическое НЕ имеет более высокий приоритет, чем логическое И
const result4: bool = !(a > b) and b > c; // !(5 > 3) and (3 > 2) = false
std.debug.print("!(a > b) and b > c = {}\n", .{result4});
}
Скомпилированный вывод:
a + b * c = 11 (a + b) * c = 16 a > b and b > c = true !(a > b) and b > c = falseДругие расширения