---
title: "@shlExact em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@shlexact-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@shlexact-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @shlExact em Zig. Shift left exato que garante que nenhum bit significativo é perdido. Exemplos práticos pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# @shlExact em Zig — Referência e Exemplos

Referência completa do @shlExact em Zig. Shift left exato que garante que nenhum bit significativo é perdido. Exemplos práticos pt-BR.


# @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

```zig
@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

```zig
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

```zig
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

```zig
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

1. **Bit flags**: Criar flags de bit com garantia de não overflow.
2. **Multiplicação por potência de 2**: Shift como multiplicação verificada.
3. **Protocolos binários**: Montar campos de bits com garantia de integridade.
4. **Criptografia**: Operações de bit que não devem perder informação.

## Diferença entre `@shlExact` e o operador `<<`

O operador `<<` padrão em Zig tem comportamento diferente conforme o modo de compilação:

- **Debug/ReleaseSafe**: panic se bits significativos forem perdidos.
- **ReleaseFast/ReleaseSmall**: undefined behavior silencioso se bits forem perdidos.

O `@shlExact` garante que bits significativos não são perdidos **independente do modo**. Se houver perda de bits, o resultado é sempre panic em safe ou undefined behavior documentado em fast. A semântica é mais explícita: o nome "Exact" comunica claramente a intenção de que o shift não deve descartar informação.

## Comparação com equivalente em C

Em C, shift left não tem verificação de overflow de bits:

```c
// C: shift silencioso, pode perder bits sem aviso
unsigned char resultado = 200 << 2; // bits perdidos silenciosamente

// C: verificação manual necessária (verbosa e propensa a erros)
unsigned char valor = 200;
unsigned char shift = 2;
if (valor > (255 >> shift)) {
    // overflow de bits
}
unsigned char resultado = valor << shift;
```

Em Zig, `@shlExact` documenta a intenção e fornece verificação automática:

```zig
// Zig: explícito e verificado
const resultado = @shlExact(@as(u8, 3), 2); // seguro: 12
// @shlExact(@as(u8, 200), 2) causaria panic — bits seriam perdidos
```

## Casos de uso avançados

### Construção de máscaras de bits em comptime

`@shlExact` é especialmente valioso em comptime para validar constantes:

```zig
const std = @import("std");

// Garante em comptime que a flag cabe no tipo
fn criarFlag(comptime bit: u5) u32 {
    return @shlExact(@as(u32, 1), bit);
}

// Erro de compilação se bit >= 32
const FLAG_ULTIMO: u32 = criarFlag(31); // ok: 0x8000_0000
// const FLAG_INVALIDO: u32 = criarFlag(32); // erro de compilação!
```

### Multiplicação verificada por potência de 2 em protocolos

```zig
fn tamanhoBloco(comptime ordem: u4) u16 {
    // Shift exato garante que o tamanho não transborda u16
    return @shlExact(@as(u16, 1), ordem);
}

const BLOCO_512: u16 = tamanhoBloco(9);   // 512
const BLOCO_4K: u16 = tamanhoBloco(12);  // 4096
const BLOCO_32K: u16 = tamanhoBloco(15); // 32768
```

## Erros comuns

**1. Confundir `@shlExact` com shift normal para multiplicação:**
```zig
// Se apenas quer multiplicar por 2 e não se importa com overflow:
const resultado = valor << 1; // OK para casos sem verificação

// Use @shlExact somente quando perder bits é um bug:
const resultado = @shlExact(valor, 1); // panic se bit mais significativo for 1
```

**2. Shift amount do tipo errado:** O segundo parâmetro deve ser do tipo `Log2(N)` para um tipo de N bits. Para `u32`, o shift amount deve ser `u5` (0..31). Passar um valor fora do intervalo causa erro de compilação.

## Perguntas Frequentes

**P: Qual é a diferença entre `@shlExact` e `@mulWithOverflow` para potências de 2?**

R: Ambos detectam overflow, mas por mecanismos diferentes. `@shlExact` verifica que nenhum bit é perdido pelo topo. `@mulWithOverflow` verifica que o resultado cabe no tipo. Para multiplicação por potência de 2, são equivalentes em resultado, mas `@shlExact` é mais eficiente (uma instrução de shift vs. multiplicação).

**P: `@shlExact` funciona com tipos signed?**

R: Sim. Para tipos signed, a semântica é a mesma: se qualquer bit 1 for deslocado para fora (incluindo bits que alterariam o sinal), ocorre panic em safe mode.

## Builtins relacionados

- [@shrExact](/builtins/shr-exact/) — Shift right exato
- [@addWithOverflow](/builtins/add-with-overflow/) — Adição com detecção de overflow
- [@clz](/builtins/clz/) — Contar zeros à esquerda
- [@popCount](/builtins/pop-count/) — Contar bits em 1

## Tutoriais relacionados

- [Operações Bit a Bit em Zig](/tutoriais/bitwise-zig/)
- [Sistema de Tipos do Zig](/tutoriais/tipos/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
