@shlExact em Zig
O @shlExact realiza um shift left (deslocamento à esquerda) e garante que nenhum bit significativo é perdido (descartado pelo topo). Se algum bit 1 for deslocado para fora, causa panic em modo safe ou undefined behavior em release. É a versão “exata” do shift, útil quando o overflow de bits não é aceitável.
Sintaxe
@shlExact(value: T, shift_amt: Log2T) T
Parâmetros
- value (
T): Valor inteiro a ser deslocado. - shift_amt (
Log2T): Número de posições para deslocar (tipo log2 do tamanho de T).
Valor de retorno
Retorna T — o resultado do shift left, garantindo que nenhum bit foi perdido.
Exemplos práticos
Exemplo 1: Shift exato seguro
const std = @import("std");
pub fn main() void {
// Shift seguro: 1 << 4 = 16 (cabe em u8)
const a: u8 = @shlExact(@as(u8, 1), 4);
std.debug.print("1 << 4 = {}\n", .{a}); // 16
// Shift seguro: 3 << 2 = 12
const b: u8 = @shlExact(@as(u8, 3), 2);
std.debug.print("3 << 2 = {}\n", .{b}); // 12
// Isso causaria panic em safe mode:
// @shlExact(@as(u8, 1), 8) — deslocaria o bit 1 para fora!
}
Exemplo 2: Construir flags com shift exato
const std = @import("std");
const Permissao = struct {
pub fn flag(comptime bit: u5) u32 {
return @shlExact(@as(u32, 1), bit);
}
};
pub fn main() void {
const LEITURA = Permissao.flag(0); // 1
const ESCRITA = Permissao.flag(1); // 2
const EXECUCAO = Permissao.flag(2); // 4
const permissoes = LEITURA | ESCRITA | EXECUCAO;
std.debug.print("Permissões: 0b{b:0>3}\n", .{permissoes}); // 0b111
}
Exemplo 3: Multiplicação por potência de 2 verificada
const std = @import("std");
fn multiplicarPor2(valor: u16, potencia: u4) !u16 {
// Usar @shlExact em vez de << para detectar overflow
return @shlExact(valor, potencia);
}
test "multiplicar por potência de 2" {
try std.testing.expect(multiplicarPor2(10, 3) catch unreachable == 80);
try std.testing.expect(multiplicarPor2(1, 15) catch unreachable == 32768);
}
Casos de uso comuns
- Bit flags: Criar flags de bit com garantia de não overflow.
- Multiplicação por potência de 2: Shift como multiplicação verificada.
- Protocolos binários: Montar campos de bits com garantia de integridade.
- Criptografia: Operações de bit que não devem perder informação.
Builtins relacionados
- @shrExact — Shift right exato
- @addWithOverflow — Adição com detecção de overflow
- @clz — Contar zeros à esquerda
- @popCount — Contar bits em 1