Rust: Operadores e expressões em Rust

Última atualização: 2026-08-26

No Rust, quase tudo é uma expressão — inclusive if e match.

Compreender a diferença entre expressões (que retornam um valor) e instruções (que não retornam um valor) é fundamental para escrever código conciso em Rust.


1. O que você vai aprender


2. A história de uma caixa

(1) Frustração: eu sempre cometo erros ao calcular descontos

Tom é gerente de uma loja de roupas e, todos os dias, precisa calcular vários descontos:

“Seria ótimo se houvesse uma calculadora que pudesse realizar cálculos automaticamente na ordem correta...”

(2) O esquema de expressões do Rust

RUST
fn main() {
    let price: f64 = 299.0;      // A piece of clothing 299 yuan
    let quantity: i32 = 3;        // Bought 3 items
    let is_member: bool = true;   // Is a member

    // Calculate all discounts with a single expression
    let total = (price * quantity as f64)           // Original Price
        * if quantity >= 3 { 0.7 } else { 0.9 }    // Volume Discount
        * if is_member { 0.95 } else { 1.0 };      // Member Discounts

    println!("Original Price: {:.2} yuan", price * quantity as f64);
    println!("Price after discount: {:.2} yuan", total);
    println!("Save: {:.2} yuan", price * quantity as f64 - total);
}

No Rust, if é uma expressão por si só e pode retornar um valor diretamente. Isso permite que o cálculo do desconto seja expresso como uma única cadeia de expressões, eliminando o risco de erros.


3. Lista de operadores

100%
graph TB
    A[Rust Operators] --> B[Arithmetic: + - * / %]
    A --> C[Comparison: == != < > <= >=]
    A --> D[Logic: && || !]
    A --> E[Bitwise Operations: & | ^ << >>]
    A --> F[Assignment: = += -= *= /=]

(1) Operadores aritméticos

Operador Exemplo Descrição
+ a + b Adição
- a - b Subtração
* a * b Multiplicação
/ a / b Divisão (truncamento inteiro)
% a % b restante
- -a Negação (unária)

A divisão de inteiros resulta em truncamento: 5 / 2 = 2 (não 2,5). Para obter um resultado em ponto flutuante, é preciso usar um tipo de ponto flutuante: 5.0 / 2.0 = 2.5.

(2) Operadores de comparação

Todos os operadores de comparação retornam o tipo bool: true ou false.

RUST
let a = 10;
let b = 20;
println!("{}", a == b);  // false
println!("{}", a != b);  // true
println!("{}", a < b);   // true

(3) Operadores lógicos

Operador Nome Exemplo Descrição
&& Operador lógico AND a && b É verdadeiro somente se ambos forem verdadeiros (curto-circuito)
` ` OU lógico
! NÃO lógico !a Inverter

Avaliação por curto-circuito: && — se o lado esquerdo for falso, o lado direito não é avaliado; || — se o lado esquerdo for verdadeiro, o lado direito não é avaliado. Isso pode ser usado no padrão “verificar antes de acessar”.

(4) Operadores bit a bit

Operador Nome Exemplo Descrição
& AND bit a bit a & b É igual a 1 somente se todos os bits correspondentes forem 1
` ` OR bit a bit `a
^ XOR bit a bit a ^ b É igual a 1 somente se os bits correspondentes forem diferentes
<< Deslocamento para a esquerda a << n Deslocamento para a esquerda em n bits (equivalente à multiplicação por 2^n)
>> Deslocamento para a direita a >> n Deslocamento para a direita em n bits (equivalente à divisão por 2^n)

4. Expressões e instruções

(1) Principais diferenças

Conceito Definição Exemplo
Expressão Possui um valor de retorno 5 + 3 retorna 8, if true { 1 } else { 0 } retorna 1
Instrução Sem valor de retorno let x = 5; Sem valor de retorno, fn foo() {} Sem valor de retorno

No Rust, os pontos-e-vírgulas determinam se algo é uma expressão ou uma instrução:

RUST
fn main() {
    let y = {
        let x = 3;
        x + 1       // No semicolons -- This is an expression, Returns 4
    };               // End of semicolon let Statement

    println!("y the value: {}", y);  // 4
}

(2) Expressões em bloco

{} O bloco de código dentro do bloco pode ser uma expressão; se a última linha não terminar com um ponto-e-vírgula, ele retorna um valor:

RUST
let result = {
    let a = 2;
    let b = 3;
    a * b           // No semicolons, This expression returns 6
};

5. Exemplos de operadores

▶ Exemplo 1: Operações aritméticas e tipos (Dificuldade ⭐)

RUST
// ============================================
// Demonstration of Arithmetic Operators——Note: Truncation in integer division
// ============================================

fn main() {
    let a = 10;
    let b = 3;

    println!("Addition: {} + {} = {}", a, b, a + b);
    println!("Subtraction: {} - {} = {}", a, b, a - b);
    println!("Multiplication: {} * {} = {}", a, b, a * b);
    println!("Integer Division: {} / {} = {} (Truncation)", a, b, a / b);
    println!("Floating-Point Division: {} / {} = {:.2}", a as f64, b as f64, a as f64 / b as f64);
    println!("Modulo: {} % {} = {}", a, b, a % b);
}

Resultado:

TEXT 📖 Somente leitura
Addition: 10 + 3 = 13
Subtraction: 10 - 3 = 7
Multiplication: 10 * 3 = 30
Integer Division: 10 / 3 = 3 (Truncation)
Floating-Point Division: 10 / 3 = 3.33
Modulo: 10 % 3 = 1

as As palavras-chave são usadas para conversão de tipos. a as f64 Converta o número inteiro em um número de ponto flutuante antes de realizar a divisão para obter um resultado em ponto flutuante.


▶ Exemplo 2: Avaliação por curto-circuito de operações lógicas (Dificuldade: ⭐⭐)

RUST
// ============================================
// Short-Circuit Evaluation of Logical Operators
// ============================================

fn main() {
    let age = 17;
    let has_id = true;

    // && Short Circuit: If the left is false, the right side is not executed
    let can_buy = age >= 18 && has_id;
    println!("Available for purchase (&&): {}", can_buy);  // false (Since the left side is already false)

    // || Short Circuit: If the left is true, the right side is not executed
    let is_ok = true || (expensive_check());
    println!("(|| Short Circuit, The right side will not be executed): {}", is_ok);
}

fn expensive_check() -> bool {
    println!("This function will not be executed!");
    true
}

Resultado:

TEXT 📖 Somente leitura
Available for purchase (&&): false
(|| Short Circuit, The right side will not be executed): true

A avaliação por curto-circuito é uma importante técnica de otimização de desempenho — ela posiciona as verificações de baixo custo à esquerda e as de alto custo à direita, a fim de evitar cálculos desnecessários.


▶ Exemplo 3: Valores de retorno de blocos de expressão (Dificuldade ⭐⭐)

RUST
// ============================================
// Using Expression Blocks to Implement Concise Assignments with Complex Conditions
// ============================================

fn main() {
    let score = 85;

    let grade = {
        if score >= 90 {
            "A"
        } else if score >= 80 {
            "B"
        } else if score >= 70 {
            "C"
        } else if score >= 60 {
            "D"
        } else {
            "F"
        }
    };  // Note: The entire if-else chain is an expression, End with a semicolon let Statement

    println!("Score: {}, Level: {}", score, grade);

    // Alternatives to Ternary Operations: Use if Expression
    let is_pass = if score >= 60 { "passed" } else { "failed" };
    println!("Result: {}", is_pass);
}

Resultado:

TEXT 📖 Somente leitura
Score: 85, Level: B
Result: passed

O Rust não possui um operador ternário (condition ? a : b), mas if é uma expressão por si só e permite obter o mesmo resultado com maior legibilidade.


▶ Exemplo 4: Operações bit a bit na prática — Indicadores de permissão e mistura de cores (Dificuldade ⭐⭐)

RUST
// ============================================
// Bitwise Operations in Practice:File Permissions and RGB Color Manipulation
// ============================================

fn main() {
    let read_perm: u8    = 0b100;   // 4
    let write_perm: u8   = 0b010;   // 2
    let exec_perm: u8    = 0b001;   // 1

    let user_perm = read_perm | write_perm;
    println!("User Permissions: {:03b} (Read+Write)", user_perm);

    let full_perm = read_perm | write_perm | exec_perm;
    println!("Full Permissions: {:03b} (Read+Write+Execute)", full_perm);

    let can_read = (user_perm & read_perm) != 0;
    let can_exec = (user_perm & exec_perm) != 0;
    println!("User-readable: {}, Executable: {}", can_read, can_exec);

    let no_write = user_perm & !write_perm;
    println!("Remove Write Permissions: {:03b}", no_write);

    let toggled = user_perm ^ exec_perm;
    println!("Toggle the execution bit: {:03b}", toggled);

    let red: u32   = 0xFF0000;
    let green: u32 = 0x00FF00;
    let blue: u32  = 0x0000FF;
    let yellow = red | green;
    let white = red | green | blue;
    println!("\nRed: {:06X}", red);
    println!("Yellow (Red|Green): {:06X}", yellow);
    println!("White (Red|Green|Blue): {:06X}", white);

    let pixel: u32 = 0xFF8040;
    let r = (pixel >> 16) & 0xFF;
    let g = (pixel >> 8)  & 0xFF;
    let b = pixel & 0xFF;
    println!("\nPixel #FF8040 → R={}, G={}, B={}", r, g, b);

    let shift_val: u8 = 1;
    println!("\n1 << 0 = {}", shift_val << 0);
    println!("1 << 1 = {}", shift_val << 1);
    println!("1 << 2 = {}", shift_val << 2);
    println!("1 << 3 = {}", shift_val << 3);
}

Resultado:

TEXT 📖 Somente leitura
User Permissions: 110 (Read+Write)
Full Permissions: 111 (Read+Write+Execute)
User-readable: true, Executable: false
Remove Write Permissions: 100
Toggle the execution bit: 111

Red: FF0000
Yellow (Red|Green): FFFF00
White (Red|Green|Blue): FFFFFF

Pixel #FF8040 → R=255, G=128, B=64

1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8

As operações bit a bit são extremamente comuns na programação de sistemas: para gerenciamento de permissões, use | para mesclar, & para verificar e & ! para remover; para cores, use | para misturar e >> + & para extrair canais; << equivale a multiplicar por uma potência de 2.


▶ Exemplo 5: Precedência de operadores e expressões compostas (Dificuldade ⭐⭐⭐)

RUST
// ============================================
// Operator Precedence in Practice + Compound Assignment Operator
// ============================================

fn main() {
    println!("=== Operator Precedence ===");
    let a = 2 + 3 * 4;
    println!("2 + 3 * 4 = {} (Multiply First, Then Add)", a);

    let b = (2 + 3) * 4;
    println!("(2 + 3) * 4 = {} (Parentheses Take Precedence)", b);

    let c = 10 - 6 / 2;
    println!("10 - 6 / 2 = {} (Multiply First, Then Subtract)", c);

    let d = true && false || true;
    println!("true && false || true = {} (&& Take precedence over ||)", d);

    let e = true || false && false;
    println!("true || false && false = {} (&& Take precedence over ||)", e);

    println!("\n=== Compound Assignment Operator ===");
    let mut score: i32 = 100;
    score += 20;
    println!("score += 20 → {}", score);
    score -= 30;
    println!("score -= 30 → {}", score);
    score *= 2;
    println!("score *= 2 → {}", score);
    score /= 7;
    println!("score /= 7 → {}", score);
    score %= 3;
    println!("score %= 3 → {}", score);

    println!("\n=== Chain Comparison(Using logical operators)===");
    let x = 50;
    let in_range = x >= 0 && x <= 100;
    let out_range = x < 0 || x > 100;
    println!("x={}, in [0,100]: {}, Out of range: {}", x, in_range, out_range);

    let charlie_score = 75;
    let bob_score = 88;
    let both_passed = charlie_score >= 60 && bob_score >= 60;
    let any_excellent = charlie_score >= 90 || bob_score >= 90;
    println!("Both passed: {}, Someone excellent: {}", both_passed, any_excellent);
}

Resultado:

TEXT 📖 Somente leitura
=== Operator Precedence ===
2 + 3 * 4 = 14 (Multiply First, Then Add)
(2 + 3) * 4 = 20 (Parentheses Take Precedence)
10 - 6 / 2 = 7 (Multiply First, Then Subtract)
true && false || true = true (&& Take precedence over ||)
true || false && false = true (&& Take precedence over ||)

=== Compound Assignment Operator ===
score += 20 → 120
score -= 30 → 90
score *= 2 → 180
score /= 7 → 25
score %= 3 → 1

=== Chain Comparison(Using logical operators)===
x=50, in [0,100]: true, Out of range: false
Both passed: true, Someone excellent: false

Prioridade dos operadores, da mais alta à mais baixa: * / %+ - → operadores de comparação → &&||. Em caso de dúvida, use parênteses; a legibilidade do código é mais importante do que a “concisão”.


❓ Perguntas Frequentes

P: A que é igual 5 / 2 em Rust? R: É igual a 2 (divisão inteira com truncamento). Para obter 2,5, é preciso escrever 5.0 / 2.0 ou 5 as f64 / 2 as f64. Isso é igual ao que acontece em C, mas diferente do Python 3 (no Python 3, / retorna um número de ponto flutuante).

P: O Rust possui os operadores ++ e --? R: Não. O Rust não possui, intencionalmente, i++ e i--, pois eles podem facilmente causar confusão nas expressões. Use i += 1 ou i = i + 1 em vez disso.

P: Qual é a diferença entre && e &? R: && é um AND lógico (de curto-circuito), e & é um AND bit a bit (sem curto-circuito). true && false retorna false, e 5 & 3 retorna 1. Os tipos também são diferentes: os operandos em ambos os lados de && são bool, enquanto os de ambos os lados de & são inteiros.

P: Como posso distinguir entre expressões e instruções? R: Verifique se há um ponto-e-vírgula no final. Um ponto-e-vírgula indica uma instrução (que não retorna um valor); a ausência de ponto-e-vírgula indica uma expressão (que retorna um valor). Em Rust, o ponto-e-vírgula funciona como um interruptor que “absorve” o valor de retorno.

P: Quais são as armadilhas da conversão de tipos com as? R: as trunca os dados silenciosamente, sem relatar um erro. Por exemplo, 300_u16 as u8 retorna 44 (bits de ordem superior truncados), enquanto -1_i32 as u32 retorna 4294967295 (reinterpretação do padrão de bits). Para uma conversão segura, recomenda-se usar try_into() (que retorna Result); use as somente quando tiver certeza de que nenhum dado será perdido.


📖 Resumo


📝 Exercícios

  1. Dificuldade ⭐: Escreva um programa que utilize a conversão as para converter i32 do tipo 5 e 2 em f64 e que gere 5 / 2 = 2.5 como resultado.
  2. Dificuldade ⭐⭐: Defina uma variável x = 5, use um bloco de expressão { x + 1 } para atribuir um valor a y e determine se x ainda está acessível fora do bloco de expressão.
  3. Dificuldade ⭐⭐⭐: Implemente uma função fn is_even(n: i32) -> bool usando operadores bit a bit, na qual você deve utilizar & operações bit a bit (e não %) para determinar a paridade.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%