---
title: "Sentinel Mismatch — Como Resolver em Zig"
url: "https://ziglang.com.br/erros/sentinel-mismatch-como-resolver-em-zig/"
markdown_url: "https://ziglang.com.br/erros/sentinel-mismatch-como-resolver-em-zig.MD"
description: "Entenda o erro de incompatibilidade de sentinel em Zig, que ocorre ao usar slices ou arrays com terminadores diferentes. Veja como resolver."
date: "2026-02-21"
author: "Zig Brasil"
---

# Sentinel Mismatch — Como Resolver em Zig

Entenda o erro de incompatibilidade de sentinel em Zig, que ocorre ao usar slices ou arrays com terminadores diferentes. Veja como resolver.


# Sentinel Mismatch — Como Resolver em Zig

## O Que Este Erro Significa

O erro de sentinel mismatch ocorre quando há incompatibilidade no valor sentinel (terminador) entre tipos de slice ou array. Em Zig, um sentinel é um valor especial colocado imediatamente após o final de um slice ou array para marcar seu término. O sentinel mais comum é `0` (null terminator), usado para compatibilidade com strings C.

Mensagens do compilador:

```
error: expected type '[:0]const u8', found '[]const u8'
```

```
error: expected sentinel value '0', found 'null'
```

Sentinels são parte do tipo em Zig — `[:0]const u8` (slice com sentinel zero) é um tipo diferente de `[]const u8` (slice sem sentinel).

## Causas Comuns

### 1. Passar Slice sem Sentinel onde Sentinel É Esperado

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

fn funcaoC(texto: [*:0]const u8) void {
    _ = texto;
}

pub fn main() void {
    const dados: []const u8 = "olá";
    funcaoC(dados.ptr); // ERRO: []const u8 não tem sentinel
}
```

### 2. Resultado de Operação de Slice Perde Sentinel

```zig
pub fn main() void {
    const texto: [:0]const u8 = "olá mundo";
    // Slicing perde o sentinel
    const parte = texto[0..3]; // tipo: *const [3]u8, sem sentinel
    const slice_sem_sentinel: []const u8 = parte;
    // Não pode usar onde [:0]const u8 é esperado
    _ = slice_sem_sentinel;
}
```

### 3. Alocação sem Sentinel

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const buffer = try allocator.alloc(u8, 100);
    defer allocator.free(buffer);

    // buffer é []u8, não [:0]u8
    // Não pode ser usado onde [:0]const u8 é esperado
    _ = buffer;
}
```

### 4. Concatenação que Perde Sentinel

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const a: []const u8 = "olá";
    const b: []const u8 = " mundo";
    const resultado = try std.mem.concat(allocator, u8, &.{ a, b });
    defer allocator.free(resultado);
    // resultado é []u8, não [:0]u8
    _ = resultado;
}
```

### 5. Função que Espera String C

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

pub fn main() void {
    var buffer: [100]u8 = undefined;
    const slice: []u8 = &buffer;
    // ERRO: puts espera [*:0]const u8 (string C)
    _ = c.puts(slice.ptr);
}
```

## Como Corrigir

### Solucao 1: Usar String Literal Diretamente

String literals em Zig já são sentinel-terminated:

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

pub fn main() void {
    // String literal é *const [N:0]u8, que coerce para [*:0]const u8
    _ = c.puts("olá mundo");
}
```

### Solucao 2: Alocar com Sentinel

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // allocSentinel adiciona o terminador automaticamente
    const buffer = try allocator.allocSentinel(u8, 100, 0);
    defer allocator.free(buffer);
    // buffer é [:0]u8 — compatível com funções C
    _ = buffer;
}
```

### Solucao 3: Usar std.fmt.bufPrintZ para Strings C

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

pub fn main() void {
    var buf: [100]u8 = undefined;
    // bufPrintZ retorna [:0]u8 (com null terminator)
    const resultado = std.fmt.bufPrintZ(&buf, "valor: {d}", .{@as(u32, 42)}) catch unreachable;
    std.debug.print("Resultado (com \\0): {s}\n", .{resultado});
}
```

### Solucao 4: Converter Slice para Sentinel Slice

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const texto: []const u8 = "olá";
    // dupeZ cria cópia com sentinel zero
    const texto_z = try allocator.dupeZ(u8, texto);
    defer allocator.free(texto_z);
    // texto_z é [:0]u8
    _ = texto_z;
}
```

### Solucao 5: Usar std.mem.span para Converter de C

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

fn funcaoQueRetornaStringC() [*:0]const u8 {
    return "dados da API C";
}

pub fn main() void {
    const c_str = funcaoQueRetornaStringC();
    // span converte [*:0]const u8 para [:0]const u8
    const zig_str: [:0]const u8 = std.mem.span(c_str);
    // E pode usar como []const u8 também
    const slice: []const u8 = zig_str;
    std.debug.print("{s} (len: {})\n", .{ slice, slice.len });
}
```

### Solucao 6: Slicing com Sentinel Preservado

```zig
pub fn main() void {
    const texto: [:0]const u8 = "olá mundo";

    // Slicing com sentinel preserva o sentinel se for até o final
    const parte = texto[0..texto.len :0]; // [:0]const u8
    _ = parte;

    // Slicing parcial perde o sentinel
    const parcial = texto[0..3]; // *const [3]u8 — sem sentinel
    _ = parcial;
}
```

## Tipos com Sentinel

| Tipo | Descrição |
|------|-----------|
| `[:0]const u8` | Slice de bytes com null terminator |
| `[:0]u8` | Slice mutável com null terminator |
| `[*:0]const u8` | Ponteiro para muitos bytes, terminado em 0 (string C) |
| `*const [N:0]u8` | Ponteiro para array de N bytes com sentinel |
| `[N:0]u8` | Array de N bytes com sentinel |

## Interoperabilidade com C

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

pub fn main() void {
    // De Zig para C
    const zig_str: [:0]const u8 = "olá";
    const c_len = c.strlen(zig_str); // Funciona — sentinel garante \0
    _ = c_len;

    // De C para Zig
    const c_str: [*:0]const u8 = "mundo";
    const zig_slice = std.mem.span(c_str); // [:0]const u8
    std.debug.print("{s}\n", .{zig_slice});
}
```

## Erros Relacionados

- [Slice type mismatch](/erros/erro-slice-type-mismatch/) — Incompatibilidade de tipos de slice
- [Type coercion failed](/erros/erro-coercion-failed/) — Falha na coerção de tipos
- [@cImport failed](/erros/erro-c-import-failed/) — Falha ao importar cabeçalho C
- [Buffer overrun](/erros/erro-buffer-overrun/) — Acesso além dos limites do buffer

## Links Úteis

- [Documentação oficial do Zig — Sentinel-Terminated Slices](https://ziglang.org/documentation/master/#Sentinel-Terminated-Slices)
- [Builtins de manipulação de ponteiros](/builtins/)
- [Receitas de interoperabilidade C](/receitas/)
- [Tutorial sobre strings em Zig](/tutoriais/)
