---
title: "@clz em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@clz-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@clz-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @clz em Zig. Conte zeros à esquerda (leading zeros) de um inteiro. Útil para log2 e detecção de bit mais significativo. pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# @clz em Zig — Referência e Exemplos

Referência completa do @clz em Zig. Conte zeros à esquerda (leading zeros) de um inteiro. Útil para log2 e detecção de bit mais significativo. pt-BR.


# @clz em Zig

O `@clz` (Count Leading Zeros) conta o número de bits **zero** consecutivos a partir do bit mais significativo (esquerda) de um valor inteiro. É uma operação fundamental para manipulação de bits, cálculo de log2, detecção do bit mais significativo e algoritmos de alocação.

## Sintaxe

```zig
@clz(value: T) Log2T
```

## Parâmetros

- **value** (`T`): Valor inteiro (unsigned ou signed) cujos zeros à esquerda serão contados.

## Valor de retorno

Retorna o número de zeros consecutivos do bit mais significativo. Para um tipo de N bits, o resultado varia de 0 (nenhum zero) a N (valor é zero).

## Exemplos práticos

### Exemplo 1: Contagem básica de leading zeros

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

pub fn main() void {
    // u8: 8 bits
    std.debug.print("clz(0b10000000) = {}\n", .{@clz(@as(u8, 0b10000000))}); // 0
    std.debug.print("clz(0b00010000) = {}\n", .{@clz(@as(u8, 0b00010000))}); // 3
    std.debug.print("clz(0b00000001) = {}\n", .{@clz(@as(u8, 0b00000001))}); // 7
    std.debug.print("clz(0b00000000) = {}\n", .{@clz(@as(u8, 0b00000000))}); // 8
}
```

### Exemplo 2: Calcular log2 inteiro

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

fn log2Floor(valor: u32) u5 {
    if (valor == 0) @panic("log2(0) indefinido");
    return 31 - @clz(valor);
}

fn proximaPotenciaDe2(valor: u32) u32 {
    if (valor <= 1) return 1;
    const bits = 32 - @clz(valor - 1);
    return @as(u32, 1) << @intCast(bits);
}

pub fn main() void {
    std.debug.print("log2(1) = {}\n", .{log2Floor(1)});     // 0
    std.debug.print("log2(8) = {}\n", .{log2Floor(8)});     // 3
    std.debug.print("log2(100) = {}\n", .{log2Floor(100)}); // 6

    std.debug.print("prox_pot2(5) = {}\n", .{proximaPotenciaDe2(5)});   // 8
    std.debug.print("prox_pot2(16) = {}\n", .{proximaPotenciaDe2(16)}); // 16
    std.debug.print("prox_pot2(17) = {}\n", .{proximaPotenciaDe2(17)}); // 32
}
```

### Exemplo 3: Número mínimo de bits necessários

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

fn bitsNecessarios(valor: u64) u7 {
    if (valor == 0) return 1;
    return @intCast(64 - @clz(valor));
}

pub fn main() void {
    std.debug.print("Bits para 255: {}\n", .{bitsNecessarios(255)});   // 8
    std.debug.print("Bits para 256: {}\n", .{bitsNecessarios(256)});   // 9
    std.debug.print("Bits para 1000: {}\n", .{bitsNecessarios(1000)}); // 10
}
```

## Casos de uso comuns

1. **log2 inteiro**: Calcular logaritmo base 2 eficientemente.
2. **Potência de 2 mais próxima**: Encontrar próxima potência de 2 acima de um valor.
3. **Alocadores**: Determinar bucket de tamanho em alocadores por tamanho.
4. **Compressão**: Codificação de comprimento variável baseada em magnitude.

## Equivalente em C e mapeamento para instruções de CPU

Em C, `__builtin_clz(x)` (GCC/Clang) faz a mesma operação para `unsigned int`. Para outros tamanhos: `__builtin_clzl` (long), `__builtin_clzll` (long long).

O Zig mapeia `@clz` para instruções nativas quando disponíveis:

| Arquitetura | Instrução |
|-------------|-----------|
| x86-64 | `LZCNT` ou `BSR` |
| ARM/AArch64 | `CLZ` |
| RISC-V | `CLZ` (extensão B) |
| WASM | `i32.clz` / `i64.clz` |

Essas são instruções de ciclo único na maioria das CPUs modernas.

## @clz vs @ctz — quando usar cada um

| Operação | Builtin | Instrução CPU |
|----------|---------|---------------|
| Bit mais significativo | `@clz` | LZCNT, BSR |
| Bit menos significativo | `@ctz` | TZCNT, BSF |
| Verificar alinhamento | `@ctz` | TZCNT |
| Calcular log2 | `@clz` | LZCNT |
| Iterar bits ligados | `@ctz` | TZCNT |

## Comportamento com zero

Quando o valor de entrada é zero:

- `@clz(0)` retorna o número total de bits do tipo (ex: 32 para `u32`)
- `@ctz(0)` retorna o número total de bits do tipo (ex: 32 para `u32`)

Isso é diferente do comportamento de `BSR`/`BSF` em x86, que produz resultado indefinido para zero. O Zig garante um resultado bem definido em todas as arquiteturas.

```zig
std.debug.print("{}\n", .{@clz(@as(u32, 0))}); // 32, sempre
```

## Aplicações práticas adicionais

**Tabelas de lookup com indexação por potência de 2**:

```zig
fn getBucket(tamanho: u32) u5 {
    // Retorna o índice do bucket correspondente à potência de 2 >= tamanho
    if (tamanho == 0) return 0;
    return @intCast(32 - @clz(tamanho - 1));
}
// tamanho 1 -> bucket 0 (2^0 = 1)
// tamanho 5 -> bucket 3 (2^3 = 8)
// tamanho 8 -> bucket 3 (2^3 = 8)
// tamanho 9 -> bucket 4 (2^4 = 16)
```

**Verificar se um valor é potência de 2**:

```zig
fn isPot2(n: u32) bool {
    if (n == 0) return false;
    // Uma potência de 2 tem exatamente 1 bit ligado
    return (n & (n - 1)) == 0;
    // Alternativa com @clz e @popCount:
    // return @popCount(n) == 1;
}
```

## Erros comuns

**Usar @clz com inteiros signed**: Embora funcione, `@clz` em valores negativos (signed) sempre retorna 0 porque o bit de sinal está ligado. Converta para unsigned antes:

```zig
const n: i32 = 100;
const zeros = @clz(@as(u32, @bitCast(n))); // correto
```

**Off-by-one em cálculos de log2**: `31 - @clz(n)` para `u32` calcula `floor(log2(n))`. Para valores que são exatamente potências de 2, o resultado é correto. Para outros valores, é o floor. Documente claramente qual você precisa.

## Perguntas Frequentes

**`@clz` funciona com tipos de bits não-padrão como `u24`?**

Sim. `@clz(@as(u24, 1))` retorna 23 (23 zeros à esquerda de um `u24` com valor 1). O Zig trata corretamente todos os tamanhos de inteiro.

**Posso usar @clz em comptime?**

Sim. Como todos os builtins aritméticos do Zig, `@clz` pode ser avaliado em tempo de compilação quando o argumento é comptime.

## Builtins relacionados

- [@ctz](/builtins/ctz/) — Contar zeros à direita (trailing zeros)
- [@popCount](/builtins/pop-count/) — Contar bits em 1
- [@bitReverse](/builtins/bit-reverse/) — Inverter ordem dos bits
- [@byteSwap](/builtins/byte-swap/) — Inverter ordem dos bytes

## 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/)
