@subWithOverflow em Zig — Referência e Exemplos

@subWithOverflow em Zig

O @subWithOverflow realiza uma subtração e indica se houve overflow (ou underflow). Retorna uma tupla com o resultado (possivelmente truncado) e um bit de overflow. Especialmente útil com tipos unsigned, onde subtrair um valor maior causa underflow.

Sintaxe

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

Parâmetros

  • a (T): Minuendo (tipo inteiro).
  • b (T): Subtraendo (mesmo tipo inteiro).

Valor de retorno

Retorna uma tupla struct { T, u1 }:

  • [0] (T): Resultado da subtração (truncado se overflow).
  • [1] (u1): 1 se houve overflow/underflow, 0 caso contrário.

Exemplos práticos

Exemplo 1: Detecção de underflow em unsigned

const std = @import("std");

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

    // Com underflow: 50 - 100 em u8
    const r2 = @subWithOverflow(@as(u8, 50), @as(u8, 100));
    std.debug.print("50 - 100 = {} (overflow: {})\n", .{ r2[0], r2[1] });
    // 50 - 100 = 206 (overflow: 1)  — wraps around
}

Exemplo 2: Subtração segura com fallback

const std = @import("std");

fn subSegura(a: u32, b: u32) u32 {
    const resultado = @subWithOverflow(a, b);
    if (resultado[1] != 0) {
        return 0; // Saturar em zero em vez de overflow
    }
    return resultado[0];
}

pub fn main() void {
    std.debug.print("{}\n", .{subSegura(100, 30)});  // 70
    std.debug.print("{}\n", .{subSegura(10, 50)});    // 0 (saturado)
}

Exemplo 3: Cálculo de diferença absoluta

const std = @import("std");

fn diferencaAbsoluta(a: u32, b: u32) u32 {
    const r = @subWithOverflow(a, b);
    if (r[1] != 0) {
        // a < b, calcular b - a
        return b - a;
    }
    return r[0];
}

pub fn main() void {
    std.debug.print("|100 - 30| = {}\n", .{diferencaAbsoluta(100, 30)}); // 70
    std.debug.print("|30 - 100| = {}\n", .{diferencaAbsoluta(30, 100)}); // 70
}

Casos de uso comuns

  1. Aritmética segura: Evitar panic por underflow em tipos unsigned.
  2. Saturação: Implementar subtração saturante (clampar em zero).
  3. Diferença absoluta: Calcular distância entre valores sem saber a ordem.
  4. Timers e contadores: Detectar wrap-around em contadores que decrementam.

Builtins relacionados

Tutoriais relacionados

Continue aprendendo Zig

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