@addWithOverflow em Zig — Referência e Exemplos

@addWithOverflow em Zig

O @addWithOverflow realiza uma adição e indica se houve overflow. Retorna uma tupla com o resultado (possivelmente truncado) e um bit de overflow. Isso permite tratar overflow explicitamente em vez de causar panic (modo safe) ou undefined behavior (modo unsafe).

Sintaxe

@addWithOverflow(a: T, b: T) struct { T, u1 }

Parâmetros

  • a (T): Primeiro operando (tipo inteiro).
  • b (T): Segundo operando (mesmo tipo inteiro).

Valor de retorno

Retorna uma tupla struct { T, u1 }:

  • [0] (T): Resultado da adição (truncado ao tamanho do tipo se houve overflow).
  • [1] (u1): 1 se houve overflow, 0 caso contrário.

Exemplos práticos

Exemplo 1: Detecção básica de overflow

const std = @import("std");

pub fn main() void {
    // Sem overflow
    const r1 = @addWithOverflow(@as(u8, 100), @as(u8, 50));
    std.debug.print("100 + 50 = {} (overflow: {})\n", .{ r1[0], r1[1] });
    // 100 + 50 = 150 (overflow: 0)

    // Com overflow: 200 + 100 = 300, mas u8 vai até 255
    const r2 = @addWithOverflow(@as(u8, 200), @as(u8, 100));
    std.debug.print("200 + 100 = {} (overflow: {})\n", .{ r2[0], r2[1] });
    // 200 + 100 = 44 (overflow: 1)  — 300 mod 256 = 44
}

Exemplo 2: Adição segura com tratamento de erro

const std = @import("std");

fn somaSegura(a: u32, b: u32) !u32 {
    const resultado = @addWithOverflow(a, b);
    if (resultado[1] != 0) {
        return error.Overflow;
    }
    return resultado[0];
}

pub fn main() void {
    const a = somaSegura(1_000_000, 2_000_000) catch |err| {
        std.debug.print("Erro: {}\n", .{err});
        return;
    };
    std.debug.print("Resultado: {}\n", .{a}); // 3000000

    const b = somaSegura(std.math.maxInt(u32), 1) catch |err| {
        std.debug.print("Erro: {s}\n", .{@errorName(err)}); // Overflow
        return;
    };
    _ = b;
}

Exemplo 3: Acumulador com detecção de limite

const std = @import("std");

fn somarArray(valores: []const u16) struct { soma: u16, overflow: bool } {
    var total: u16 = 0;
    var teve_overflow = false;

    for (valores) |v| {
        const r = @addWithOverflow(total, v);
        total = r[0];
        if (r[1] != 0) teve_overflow = true;
    }

    return .{ .soma = total, .overflow = teve_overflow };
}

pub fn main() void {
    const dados = [_]u16{ 10000, 20000, 30000, 10000 };
    const resultado = somarArray(&dados);

    if (resultado.overflow) {
        std.debug.print("AVISO: overflow detectado!\n", .{});
    }
    std.debug.print("Soma (possivelmente truncada): {}\n", .{resultado.soma});
}

Casos de uso comuns

  1. Aritmética segura: Detectar overflow sem causar panic.
  2. Criptografia: Operações que precisam de wrap-around explícito.
  3. Validação de entrada: Verificar se somas de valores do usuário excedem limites.
  4. Contadores: Detectar quando um contador atinge o valor máximo.

Builtins relacionados

Tutoriais relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.