---
title: "Sentinel em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/sentinel-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/sentinel-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda sentinel-terminated arrays em Zig: arrays e slices com valor terminador, essenciais para interop com C. Guia completo em pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Sentinel em Zig — O que é e Como Usar

Entenda sentinel-terminated arrays em Zig: arrays e slices com valor terminador, essenciais para interop com C. Guia completo em pt-BR.


# Sentinel em Zig — O que é e Como Usar

## Definição

Um **sentinel-terminated array** (array terminado por sentinela) em Zig é um array ou slice que possui um valor especial — o **sentinel** — imediatamente após o último elemento. O exemplo mais comum é a string terminada em zero (`[:0]u8`), equivalente às strings C (`char*` com `\0` no final).

A sintaxe `[N:s]T` declara um array de `N` elementos do tipo `T` com sentinela `s`. Para slices, `[:s]T` indica um slice com sentinel.

## Por que Sentinels Importam

1. **Interoperabilidade com C**: APIs C esperam strings terminadas em null. Zig facilita a criação e uso desses tipos.
2. **Segurança de tipos**: O tipo carrega a informação do sentinel, garantindo em tempo de compilação que o terminador está presente.
3. **Compatibilidade**: Sentinel-terminated slices podem ser convertidos para slices normais sem custo.
4. **String literals**: Todas as string literals em Zig são `*const [N:0]u8` — terminadas em zero automaticamente.

## Exemplo Prático

### Strings Terminadas em Zero

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

pub fn main() void {
    // String literal é automaticamente sentinel-terminated
    const mensagem: [:0]const u8 = "Olá, Zig!";

    // Acessar o sentinel
    std.debug.print("Último char: '{}'\n", .{mensagem[mensagem.len]}); // 0

    // Passar para função C
    _ = std.c.printf("%s\n", mensagem.ptr);
}
```

### Arrays com Sentinel Customizado

```zig
// Array de 3 elementos terminado com 0xFF
const dados: [3:0xFF]u8 = .{ 10, 20, 30 };

// O elemento na posição [3] é 0xFF (o sentinel)
std.debug.print("Sentinel: {}\n", .{dados[3]}); // 255
```

### Convertendo entre Tipos

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

pub fn main() void {
    // Sentinel-terminated → slice normal (sem custo)
    const sentinel_slice: [:0]const u8 = "Zig Brasil";
    const slice_normal: []const u8 = sentinel_slice;
    _ = slice_normal;

    // Array → sentinel slice
    var array: [5:0]u8 = .{ 'H', 'e', 'l', 'l', 'o' };
    const s: [:0]u8 = &array;
    _ = s;
}
```

### Interop com C

```zig
const std = @import("std");
const c = @cImport({
    @cInclude("stdio.h");
    @cInclude("string.h");
});

pub fn main() void {
    const zig_string: [:0]const u8 = "Texto do Zig";

    // strlen espera [*:0]const u8 — compatível automaticamente
    const tamanho = c.strlen(zig_string);
    std.debug.print("Tamanho via C: {}\n", .{tamanho});
}
```

### Criando Sentinel Slice Dinamicamente

```zig
fn criarStringC(allocator: std.mem.Allocator, texto: []const u8) ![:0]u8 {
    const resultado = try allocator.allocSentinel(u8, texto.len, 0);
    @memcpy(resultado, texto);
    return resultado;
}
```

## Tipos com Sentinel

| Tipo | Descrição |
|------|-----------|
| `[N:0]u8` | Array de N bytes + null terminator |
| `[:0]u8` | Slice de bytes com null terminator |
| `[*:0]u8` | Many-pointer terminado em null |
| `[N:s]T` | Array de N elementos com sentinel `s` |

## Boas Práticas

- **Sempre use `[:0]const u8` ao passar strings para C**: Isso garante em tempo de compilação que o terminador zero está presente, eliminando a possibilidade de buffer overread no lado C.
- **Use `allocSentinel` para strings dinâmicas**: `allocator.allocSentinel(u8, len, 0)` é a forma correta de alocar strings terminadas em null no heap.
- **Prefira `[]const u8` internamente**: Internamente no código Zig, use slices normais. Converta para `[:0]` apenas no ponto de interop com C.
- **Conheça `std.mem.sliceTo`**: `std.mem.sliceTo(ptr, 0)` converte um `[*:0]u8` (ponteiro com sentinel) para um slice `[:0]u8` calculando o comprimento ao encontrar o zero.

## Como o Compilador Garante a Segurança

O tipo `[:0]u8` carrega informação sobre o sentinel no sistema de tipos. Isso significa que passar um `[]u8` simples (sem sentinel garantido) para uma função que espera `[:0]u8` é um **erro de compilação**. O programador é forçado a usar os tipos corretos, e o compilador verifica a presença do sentinel estaticamente sempre que possível.

Para string literals, o Zig automaticamente adiciona o byte zero após os dados, de modo que `"hello"` tem o tipo `*const [5:0]u8` — um ponteiro para um array de 5 bytes com sentinel zero. Isso torna literals de string diretamente compatíveis com APIs C sem qualquer conversão ou cópia.

## Armadilhas Comuns

- **Assumir que todo `[]const u8` é terminado em zero**: Slices normais NÃO têm sentinel. Só `[:0]const u8` garante o terminador.
- **Acessar além do sentinel**: O sentinel está em `slice[slice.len]`, mas acessar `slice[slice.len + 1]` é comportamento indefinido.
- **Esquecer de usar `allocSentinel`**: Ao alocar memória para strings que serão passadas para C, use `allocSentinel` em vez de `alloc`.
- **Converter sem cuidado**: Converter `[]u8` para `[:0]u8` requer que o sentinela realmente exista na memória. Use `std.mem.sliceTo` para conversão segura.

## Termos Relacionados

- [Slice](/glossario/slice/) — Referência a sequência de memória
- [Pointer Types](/glossario/pointer-types/) — Tipos de ponteiro em Zig
- [usize](/glossario/usize/) — Tipo de índice e comprimento

## Tutoriais Relacionados

- [Strings e Arrays em Zig](/tutoriais/strings-e-arrays-zig/)
- [Zig e C — Interoperabilidade](/tutoriais/zig-c-interoperabilidade/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
