Como Converter entre Tipos de String em Zig
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
- Concatenar Strings — Junte diferentes tipos de string
- 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