Inline em Zig — O que é e Como Usar
Definição
A palavra-chave inline em Zig serve para duas finalidades principais: forçar o inlining de funções e desenrolar loops em tempo de compilação. Quando aplicada a uma função, o corpo da função é substituído diretamente no local da chamada. Quando aplicada a um for ou while, o loop é desenrolado (unrolled), e cada iteração é “colada” sequencialmente no código gerado.
Por que Inline Importa
- Performance: Elimina o custo de chamada de função (push/pop de stack frame, salto).
- Comptime em loops:
inline forpermite iterar sobre tipos e valores em tempo de compilação. - Otimização manual: Quando o compilador não faz inline automaticamente, você pode forçar.
- Metaprogramação: Combinado com comptime, permite gerar código especializado.
Exemplo Prático
Inline For (Desenrolamento de Loop)
const std = @import("std");
fn somaVetorial(vetor: @Vector(4, f32)) f32 {
// Desenrola em 4 somas individuais em tempo de compilação
var resultado: f32 = 0;
const campos = [_]comptime_int{ 0, 1, 2, 3 };
inline for (campos) |i| {
resultado += vetor[i];
}
return resultado;
}
pub fn main() void {
const v: @Vector(4, f32) = .{ 1.0, 2.0, 3.0, 4.0 };
std.debug.print("Soma: {d}\n", .{somaVetorial(v)}); // 10.0
}
Inline For com Tipos (Metaprogramação)
const std = @import("std");
fn imprimir(args: anytype) void {
inline for (std.meta.fields(@TypeOf(args))) |campo| {
std.debug.print("{s}: {}\n", .{ campo.name, @field(args, campo.name) });
}
}
pub fn main() void {
imprimir(.{ .nome = "Zig", .versao = 13, .estavel = true });
}
Inline Function
// Forçar inlining — o corpo será copiado no local da chamada
inline fn max(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
return if (a > b) a else b;
}
pub fn main() void {
// Não há chamada de função no código gerado
const resultado = max(@as(u32, 10), @as(u32, 20));
std.debug.print("Max: {}\n", .{resultado});
}
Inline While
fn contar(comptime n: usize) [n]usize {
var resultado: [n]usize = undefined;
comptime var i: usize = 0;
inline while (i < n) : (i += 1) {
resultado[i] = i * i;
}
return resultado;
}
const quadrados = contar(5); // [0, 1, 4, 9, 16]
Inline vs Comptime
| Aspecto | inline | comptime |
|---|---|---|
| Funções | Substitui corpo no local da chamada | Executa inteiramente na compilação |
| Loops | Desenrola iterações | Avalia valores em compilação |
| Resultado | Código mais rápido, binário maior | Constante embutida no binário |
Na prática, inline for frequentemente trabalha em conjunto com valores comptime:
inline for (comptime std.meta.fieldNames(MeuTipo)) |nome| {
// cada iteração é resolvida em compilação
}
Armadilhas Comuns
- Binário inchado: Funções inline muito grandes, chamadas em muitos lugares, aumentam o tamanho do binário significativamente.
- Inline desnecessário: O compilador de Zig (via LLVM) já faz inlining automático quando vantajoso. Use
inlineexplícito apenas quando necessário. - Confundir
inline forcomfornormal:inline forrequer que o iterável seja conhecido em comptime. Um slice dinâmico não pode ser usado cominline for. - Debug mais difícil: Código inline não aparece como chamada de função separada no stack trace.
Termos Relacionados
- Comptime — Execução em tempo de compilação
- Release Modes — Modos de compilação e otimização
- Vector/SIMD — Tipos vetoriais otimizados