---
title: "@call em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@call-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@call-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @call em Zig. Chame funções com controle avançado: inlining forçado, never_tail, never_inline e async. Exemplos pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# @call em Zig — Referência e Exemplos

Referência completa do @call em Zig. Chame funções com controle avançado: inlining forçado, never_tail, never_inline e async. Exemplos pt-BR.


# @call em Zig

O `@call` invoca uma função com **controle avançado** sobre como a chamada é realizada. Permite forçar inlining, prevenir tail calls, controlar otimizações de chamada e especificar o stack frame. Útil para código de alta performance, recursão e interoperabilidade.

## Sintaxe

```zig
@call(modifier: std.builtin.CallModifier, function: anytype, args: anytype) ReturnType
```

## Parâmetros

- **modifier** (`CallModifier`): Controle sobre como a chamada é feita.
- **function**: A função a ser chamada.
- **args**: Tupla com os argumentos da função.

## Valor de retorno

Retorna o mesmo tipo que a função chamada retornaria.

## Modifiers disponíveis

| Modifier | Descrição |
|----------|-----------|
| `.auto` | Comportamento padrão (igual a chamada normal) |
| `.always_inline` | Forçar inlining (erro se não for possível) |
| `.never_inline` | Nunca inline (sempre chamada de função) |
| `.never_tail` | Nunca otimizar como tail call |
| `.compile_time` | Forçar avaliação em comptime |

## Exemplos práticos

### Exemplo 1: Forçar inlining

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

fn somaRapida(a: u64, b: u64) u64 {
    return a + b;
}

pub fn main() void {
    // Forçar que somaRapida seja inlined
    const resultado = @call(.always_inline, somaRapida, .{
        @as(u64, 42),
        @as(u64, 58),
    });

    std.debug.print("Soma: {}\n", .{resultado}); // 100
}
```

### Exemplo 2: Prevenir tail call em recursão

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

fn fatorial(n: u64) u64 {
    if (n <= 1) return 1;

    // Prevenir tail call para manter stack frame (útil para debug)
    return n * @call(.never_tail, fatorial, .{n - 1});
}

pub fn main() void {
    std.debug.print("10! = {}\n", .{fatorial(10)}); // 3628800
}
```

### Exemplo 3: Chamada genérica de função

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

fn chamarComLog(funcao: anytype, args: anytype) @TypeOf(@call(.auto, funcao, args)) {
    std.debug.print("Chamando função...\n", .{});
    const resultado = @call(.auto, funcao, args);
    std.debug.print("Função retornou.\n", .{});
    return resultado;
}

fn multiplicar(a: i32, b: i32) i32 {
    return a * b;
}

fn saudar(nome: []const u8) void {
    std.debug.print("Olá, {s}!\n", .{nome});
}

pub fn main() void {
    const produto = chamarComLog(multiplicar, .{ @as(i32, 6), @as(i32, 7) });
    std.debug.print("Produto: {}\n", .{produto}); // 42

    chamarComLog(saudar, .{"Zig Brasil"});
}
```

## Casos de uso comuns

1. **Performance**: Forçar inlining de funções críticas em hot paths.
2. **Debugging**: Prevenir tail calls para manter stack traces completos.
3. **Wrappers genéricos**: Criar decoradores/interceptadores de funções.
4. **Benchmarks**: Prevenir que o compilador otimize chamadas de teste.
5. **Recursão controlada**: Garantir que recursão use o stack conforme esperado.

## @call vs chamada normal

```zig
// Equivalentes:
const r1 = funcao(a, b);
const r2 = @call(.auto, funcao, .{ a, b });

// Mas @call permite controle extra:
const r3 = @call(.always_inline, funcao, .{ a, b });  // Forçar inline
const r4 = @call(.never_tail, funcao, .{ a, b });     // Sem tail call
```

## Quando usar cada modifier

**`.auto`**: Use quando não precisa de controle especial. Equivalente à chamada direta `funcao(args)`.

**`.always_inline`**: Use em funções pequenas e críticas de performance que devem eliminar o overhead de chamada. O compilador emite erro se não for possível fazer inline (por exemplo, funções recursivas não podem ser inlined).

**`.never_inline`**: Use para:
- Forçar que uma função seja um símbolo separado no binário (útil para profiling)
- Evitar crescimento excessivo do código em debug builds
- Garantir que o stack trace apareça corretamente

**`.never_tail`**: Use quando a semântica de tail call quebraria a lógica. Por exemplo, em código que usa `defer` ou que depende do stack frame após o retorno.

**`.compile_time`**: Use quando quer garantir que uma função seja avaliada em comptime. Útil para verificar que uma otimização comptime está sendo aplicada.

## Diferença entre @call e inline keyword

O Zig tem duas formas de forçar inlining:

```zig
// Keyword inline na definição — sempre inline, sem escolha
inline fn somaRapida(a: u32, b: u32) u32 { return a + b; }

// @call .always_inline — inline no ponto de chamada
fn soma(a: u32, b: u32) u32 { return a + b; }
const r = @call(.always_inline, soma, .{a, b});
```

A diferença: `inline fn` força inline em **todos** os call sites. `@call(.always_inline, ...)` força inline apenas naquele call site específico, deixando outros call sites com o comportamento padrão.

## @call com ponteiros de função

`@call` é especialmente útil com ponteiros de função, onde chamadas normais nunca são inlined:

```zig
const Transformador = *const fn(u32) u32;

fn aplicar(func: Transformador, valor: u32) u32 {
    // Aqui, @call(.auto, func, .{valor}) é igual a func(valor)
    // Mas com .always_inline, o compilador pode tentar inline via PGO
    return @call(.auto, func, .{valor});
}
```

## Equivalente em C

Em C, `__attribute__((always_inline))` e `__attribute__((noinline))` são colocados na definição da função, não no call site. O Zig oferece mais granularidade com `@call`.

## Erros comuns

**Usar `.always_inline` em funções recursivas**: O compilador emitirá um erro porque funções recursivas não podem ser inlined completamente. Use `.never_tail` em vez disso para controlar a recursão.

**Esquecer que `.compile_time` exige que os argumentos sejam comptime**: Se os argumentos não forem conhecidos em tempo de compilação, o compilador emitirá um erro.

## Perguntas Frequentes

**`@call` tem overhead em comparação com uma chamada normal?**

Com `.auto`, não há overhead — o compilador gera código idêntico. Com outros modifiers, pode haver custo ou benefício dependendo do contexto.

**Posso usar @call com métodos de struct?**

Sim. Passe a função explicitamente como `Struct.metodo` e inclua `self` nos argumentos:

```zig
const r = @call(.always_inline, MeuTipo.calcular, .{&instancia, argumento});
```

## Builtins relacionados

- [@import](/builtins/import/) — Importar módulos
- [@typeInfo](/builtins/type-info/) — Introspecção para chamadas genéricas
- [@TypeOf](/builtins/type-of/) — Obter tipo de retorno de funções
- [@compileError](/builtins/compile-error/) — Erro se inlining impossível

## Tutoriais relacionados

- [Performance em Zig](/tutoriais/zig-simd-performance/)
- [Comptime em Zig](/tutoriais/comptime-em-zig/)
- [Zig Design Patterns](/tutoriais/zig-design-patterns/)
