@min em Zig
O @min retorna o menor de dois valores. Funciona com inteiros, floats e valores comptime. Se os dois valores forem conhecidos em comptime, o resultado também é comptime. Este builtin substitui a necessidade de escrever expressões condicionais if (a < b) a else b.
Sintaxe
@min(a: T, b: T) T
Parâmetros
- a (
T): Primeiro valor. - b (
T): Segundo valor (mesmo tipo ou coercível).
Valor de retorno
Retorna T — o menor dos dois valores.
Exemplos práticos
Exemplo 1: Uso básico com inteiros e floats
const std = @import("std");
pub fn main() void {
const a: u32 = 42;
const b: u32 = 100;
std.debug.print("min({}, {}) = {}\n", .{ a, b, @min(a, b) }); // 42
const x: f64 = 3.14;
const y: f64 = 2.71;
std.debug.print("min({d}, {d}) = {d}\n", .{ x, y, @min(x, y) }); // 2.71
}
Exemplo 2: Limitar tamanho de buffer
const std = @import("std");
fn copiarLimitado(destino: []u8, origem: []const u8) usize {
const tamanho = @min(destino.len, origem.len);
@memcpy(destino[0..tamanho], origem[0..tamanho]);
return tamanho;
}
pub fn main() void {
var buffer: [5]u8 = undefined;
const texto = "Hello, Zig Brasil!";
const copiados = copiarLimitado(&buffer, texto);
std.debug.print("Copiados: {s} ({} bytes)\n", .{ buffer[0..copiados], copiados });
// "Hello" (5 bytes)
}
Exemplo 3: Clamp (limitar a intervalo)
const std = @import("std");
fn clamp(valor: i32, minimo: i32, maximo: i32) i32 {
return @max(minimo, @min(valor, maximo));
}
pub fn main() void {
std.debug.print("{}\n", .{clamp(5, 0, 10)}); // 5 (dentro do intervalo)
std.debug.print("{}\n", .{clamp(-3, 0, 10)}); // 0 (abaixo do mínimo)
std.debug.print("{}\n", .{clamp(15, 0, 10)}); // 10 (acima do máximo)
}
Casos de uso comuns
- Limitar tamanho: Garantir que um índice não exceda o tamanho do array.
- Clamping: Combinar com
@maxpara restringir valores a um intervalo. - Processamento de dados: Encontrar mínimo em sequências.
- Dimensionamento: Limitar tamanho de buffers, janelas, etc.
Padrão idiomático: copiar com limite seguro
O uso mais frequente de @min em Zig é garantir que uma operação de cópia ou acesso não ultrapasse o tamanho disponível:
fn appendLimitado(destino: *[128]u8, pos: *usize, origem: []const u8) void {
const espaco_restante = destino.len - pos.*;
const a_copiar = @min(origem.len, espaco_restante);
@memcpy(destino[pos.*..][0..a_copiar], origem[0..a_copiar]);
pos.* += a_copiar;
}
Esse padrão elimina verificações manuais de bounds e garante que nunca haverá buffer overflow.
Comportamento com floats e NaN
Assim como @max, o @min segue a semântica do IEEE 754: se um dos operandos for NaN, o resultado é o outro operando:
const nan = std.math.nan(f64);
const resultado = @min(nan, 5.0); // resultado == 5.0 (NaN não se propaga)
Isso pode ser surpreendente, mas é o comportamento padrão do IEEE 754-2008 para minNum. Se você precisa que NaN se propague, verifique explicitamente com std.math.isNan antes de chamar @min.
Comparação com C equivalente
Em C, não há função min na biblioteca padrão para todos os tipos. As abordagens comuns têm problemas:
// Macro com avaliação dupla — perigosa com side effects
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int x = MIN(++a, ++b); // BUG: a ou b incrementado duas vezes!
// C99 em <math.h> — apenas para double
double m = fmin(x, y);
Em Zig, @min é um builtin seguro, genérico e sem avaliação dupla:
const m = @min(a, b); // sem side effects duplicados, qualquer tipo numérico
@min com @max para clamping robusto
A combinação dos dois builtins é o idioma padrão para clamping em Zig:
// Garantir que volume fique entre 0.0 e 1.0
const volume_seguro = @max(0.0, @min(volume_entrada, 1.0));
// Garantir que índice seja válido para o array
const indice_seguro = @min(indice, array.len - 1);
// Limitar latência entre 100ms e 30000ms
const latencia_ms = @max(@as(u32, 100), @min(latencia_config, 30_000));
Esse padrão é tão comum que a biblioteca padrão oferece std.math.clamp(val, min, max) como atalho.
Perguntas Frequentes
P: @min funciona com vetores SIMD (@Vector)?
Sim. Assim como @max, o @min é compatível com @Vector. O compilador pode gerar instruções SIMD como vminps (AVX) ou vminss para comparações paralelas de múltiplos valores, o que é muito mais eficiente que comparar elemento a elemento em um loop.
P: Há diferença de performance entre @min(a, b) e if (a < b) a else b?
Em otimizações habilitadas, o compilador geralmente gera o mesmo código para ambos. No entanto, @min comunica a intenção mais claramente e pode ser mais facilmente vetorizado pelo compilador. Para código de performance crítica, prefira @min.
P: @min funciona com tipos comptime_int e comptime_float?
Sim. Se ambos os operandos forem comptime, o resultado também é comptime e o cálculo ocorre inteiramente em tempo de compilação sem custo em runtime. Isso é útil para calcular constantes comptime como tamanhos de arrays.
Builtins relacionados
- @max — Retorna o maior de dois valores
- @addWithOverflow — Aritmética com detecção de overflow
- @as — Conversão de tipo quando os operandos diferem