@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):1se houve overflow,0caso 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
- Aritmética segura: Detectar overflow sem causar panic.
- Criptografia: Operações que precisam de wrap-around explícito.
- Validação de entrada: Verificar se somas de valores do usuário excedem limites.
- Contadores: Detectar quando um contador atinge o valor máximo.
Builtins relacionados
- @subWithOverflow — Subtração com detecção de overflow
- @mulWithOverflow — Multiplicação com detecção de overflow
- @shlExact — Shift left exato
- @min / @max — Limitar valores