Em Zig, não existe um único tipo “string”. Em vez disso, existem vários tipos relacionados que representam sequências de bytes. Entender como converter entre eles é essencial para trabalhar eficientemente com texto em Zig.
Os Tipos de String em Zig
Os principais tipos usados como strings em Zig são:
| Tipo | Descrição |
|---|---|
[]const u8 | Slice imutável de bytes (o tipo mais comum para strings) |
[]u8 | Slice mutável de bytes |
[N]u8 | Array de tamanho fixo |
[:0]const u8 | Slice com terminador nulo (sentinel) |
[*:0]const u8 | Ponteiro para string com terminador nulo (estilo C) |
[*]const u8 | Ponteiro para sequência de bytes (sem tamanho) |
Literais de String
Literais de string em Zig são do tipo *const [N:0]u8, que coerce automaticamente para []const u8 e [:0]const u8.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Literal é *const [9:0]u8, mas coerce para []const u8
const texto: []const u8 = "Olá Mundo";
try stdout.print("Tipo slice: \"{s}\" (len={d})\n", .{ texto, texto.len });
// Também coerce para [:0]const u8 (com sentinel)
const sentinel: [:0]const u8 = "Olá Mundo";
try stdout.print("Com sentinel: \"{s}\" (len={d})\n", .{ sentinel, sentinel.len });
// Acessar o terminador nulo
try stdout.print("Byte após fim: {d}\n", .{sentinel[sentinel.len]});
}
Saída esperada:
Tipo slice: "Olá Mundo" (len=9)
Com sentinel: "Olá Mundo" (len=9)
Byte após fim: 0
Converter Array para Slice
Arrays de u8 podem ser convertidos para slices usando o operador de endereço &.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Array fixo para slice
const array: [5]u8 = .{ 'H', 'e', 'l', 'l', 'o' };
const slice: []const u8 = &array;
try stdout.print("Array como slice: \"{s}\"\n", .{slice});
// Array mutável para slice mutável
var buf: [10]u8 = undefined;
@memcpy(buf[0..5], "Mundo");
const slice_mut: []u8 = buf[0..5];
try stdout.print("Slice mutável: \"{s}\"\n", .{slice_mut});
// Modificar através do slice mutável
slice_mut[0] = 'Z';
try stdout.print("Após modificar: \"{s}\"\n", .{slice_mut});
}
Saída esperada:
Array como slice: "Hello"
Slice mutável: "Mundo"
Após modificar: "Zundo"
Converter Slice para Array de Tamanho Fixo
Use slice[0..N].* para converter um slice em um array de tamanho fixo (quando o tamanho é conhecido em comptime).
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const slice: []const u8 = "Hello Zig!";
// Converter slice para array de tamanho fixo
const array: [5]u8 = slice[0..5].*;
try stdout.print("Array fixo: \"{s}\"\n", .{&array});
// Usar com funções que esperam arrays
const primeiros: [3]u8 = slice[0..3].*;
try stdout.print("Primeiros 3: \"{s}\"\n", .{&primeiros});
}
Saída esperada:
Array fixo: "Hello"
Primeiros 3: "Hel"
Trabalhar com Strings Sentinel (Terminador Nulo)
Strings com terminador nulo são necessárias para interoperar com código C.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// [:0]const u8 para []const u8 - apenas perde o sentinel
const sentinel: [:0]const u8 = "Hello";
const slice: []const u8 = sentinel;
try stdout.print("Sentinel -> Slice: \"{s}\" (len={d})\n", .{ slice, slice.len });
// []const u8 para [:0]const u8 - precisa verificar ou criar
// Se souber que tem sentinel, use @ptrCast
// Para criar uma cópia com sentinel:
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const sem_sentinel: []const u8 = "Texto dinâmico";
const com_sentinel = try allocator.dupeZ(u8, sem_sentinel);
defer allocator.free(com_sentinel);
try stdout.print("Com sentinel: \"{s}\" (byte final: {d})\n", .{
com_sentinel, com_sentinel[com_sentinel.len],
});
}
Saída esperada:
Sentinel -> Slice: "Hello" (len=5)
Com sentinel: "Texto dinâmico" (byte final: 0)
Converter Ponteiro Estilo C para Slice
Ao trabalhar com APIs C, você frequentemente recebe [*:0]const u8. Use std.mem.span para converter.
const std = @import("std");
// Simulando uma função C que retorna string
fn funcaoC() [*:0]const u8 {
return "Retorno da função C";
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const c_str = funcaoC();
// Converter ponteiro C para slice Zig usando std.mem.span
const zig_str: [:0]const u8 = std.mem.span(c_str);
try stdout.print("String C como Zig: \"{s}\" (len={d})\n", .{ zig_str, zig_str.len });
// Também pode usar como []const u8
const slice: []const u8 = std.mem.span(c_str);
try stdout.print("Como slice: \"{s}\"\n", .{slice});
}
Saída esperada:
String C como Zig: "Retorno da função C" (len=19)
Como slice: "Retorno da função C"
Criar String a Partir de Bytes Individuais
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Criar string a partir de bytes individuais
var builder = std.ArrayList(u8).init(allocator);
defer builder.deinit();
const bytes = [_]u8{ 72, 101, 108, 108, 111 }; // "Hello" em ASCII
try builder.appendSlice(&bytes);
try builder.append('!');
try stdout.print("De bytes: \"{s}\"\n", .{builder.items});
// Converter ArrayList para slice owned
const resultado = try builder.toOwnedSlice();
defer allocator.free(resultado);
try stdout.print("Owned: \"{s}\" (len={d})\n", .{ resultado, resultado.len });
}
Saída esperada:
De bytes: "Hello!"
Owned: "Hello!" (len=6)
Duplicar Strings com Alocador
Para criar cópias independentes de strings, use allocator.dupe ou allocator.dupeZ.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const original = "Texto original";
// dupe: cópia sem sentinel
const copia = try allocator.dupe(u8, original);
defer allocator.free(copia);
try stdout.print("Cópia: \"{s}\"\n", .{copia});
// dupeZ: cópia com sentinel nulo
const copia_z = try allocator.dupeZ(u8, original);
defer allocator.free(copia_z);
try stdout.print("Cópia Z: \"{s}\" (sentinel: {d})\n", .{
copia_z, copia_z[copia_z.len],
});
}
Saída esperada:
Cópia: "Texto original"
Cópia Z: "Texto original" (sentinel: 0)
Tabela de Conversões
| De | Para | Método |
|---|---|---|
[N]u8 | []const u8 | &array |
[]const u8 | [N]u8 | slice[0..N].* |
[:0]const u8 | []const u8 | Conversão implícita |
[]const u8 | [:0]const u8 | allocator.dupeZ() |
[*:0]const u8 | [:0]const u8 | std.mem.span() |
[]const u8 | Cópia independente | allocator.dupe() |
Veja Também
- Formatar Strings com std.fmt — Crie strings formatadas
- Arrays Dinâmicos com ArrayList — Construa strings incrementalmente
- Usando GeneralPurposeAllocator — Alocação para cópias de strings