---
title: "Type Coercion em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/type-coercion-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/type-coercion-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda type coercion (coerção de tipos) em Zig: regras de conversão implícita e explícita entre tipos. Segurança sem overhead. Guia pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Type Coercion em Zig — O que é e Como Usar

Entenda type coercion (coerção de tipos) em Zig: regras de conversão implícita e explícita entre tipos. Segurança sem overhead. Guia pt-BR.


# Type Coercion em Zig — O que é e Como Usar

## Definição

**Type coercion** (coerção de tipos) em Zig é o processo de converter um valor de um tipo para outro. Zig possui um sistema de coerção cuidadosamente projetado que permite conversões **implícitas** apenas quando são **seguras** e sem perda de informação. Para conversões que podem perder dados ou alterar a semântica, Zig exige conversão **explícita** usando builtins como `@intCast`, `@floatFromInt`, `@ptrCast`, etc.

Essa abordagem elimina uma classe inteira de bugs comuns em C, onde conversões implícitas silenciosas podem truncar valores ou mudar sinais.

## Por que Type Coercion Importa

1. **Segurança**: Conversões que podem perder dados exigem declaração explícita do programador.
2. **Clareza**: O código expressa exatamente onde conversões acontecem.
3. **Previsibilidade**: Sem surpresas de promoção implícita como em C (integer promotion rules).
4. **Portabilidade**: O comportamento é o mesmo em todas as arquiteturas.

## Exemplo Prático

### Coerções Implícitas (Seguras)

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

pub fn main() void {
    // comptime_int para qualquer tipo inteiro que comporte o valor
    const a: u32 = 42;
    const b: i64 = 42;

    // Widening: tipo menor para tipo maior (sem perda)
    const c: u16 = 100;
    const d: u32 = c; // u16 -> u32 implícito

    // Ponteiro para slice
    var array = [_]u8{ 1, 2, 3 };
    const slice: []u8 = &array; // *[3]u8 -> []u8 implícito

    // const qualification: T -> const T
    const ptr_mut: *u32 = @constCast(&a);
    _ = ptr_mut;

    std.debug.print("{} {} {}\n", .{ d, b, slice.len });
}
```

### Coerções Explícitas (Potencialmente Inseguras)

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

pub fn main() void {
    // Narrowing: tipo maior para tipo menor (pode perder dados)
    const grande: u32 = 200;
    const pequeno: u8 = @intCast(grande); // explícito!

    // Float para inteiro (perde parte fracionária)
    const pi: f64 = 3.14;
    const inteiro: i32 = @intFromFloat(pi); // 3

    // Inteiro para float
    const n: i32 = 42;
    const f: f64 = @floatFromInt(n); // 42.0

    std.debug.print("{} {} {d}\n", .{ pequeno, inteiro, f });
}
```

### Coerção com Optionals e Error Unions

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

fn buscar(id: u32) ?[]const u8 {
    if (id == 1) return "encontrado"; // []const u8 -> ?[]const u8 implícito
    return null;
}

fn calcular(x: u32) !u32 {
    if (x == 0) return error.DivisaoPorZero;
    return 100 / x; // u32 -> !u32 implícito
}

pub fn main() void {
    const resultado = buscar(1);
    if (resultado) |valor| {
        std.debug.print("{s}\n", .{valor});
    }

    const calc = calcular(5) catch 0;
    std.debug.print("{}\n", .{calc}); // 20
}
```

## Regras de Coerção Implícita

| De | Para | Permitido |
|----|------|----------|
| `comptime_int` | Qualquer inteiro que comporte | Sim |
| `comptime_float` | `f32`, `f64` | Sim |
| `u8` | `u16`, `u32`, `u64` | Sim (widening) |
| `u32` | `u16`, `u8` | Apenas explícito (`@intCast`) |
| `*[N]T` | `[]T` | Sim |
| `T` | `?T` | Sim |
| `T` | `E!T` | Sim |
| `*T` | `*const T` | Sim |

## O Papel de @as na Coerção

O builtin `@as(T, expr)` força a coerção de `expr` para o tipo `T`. Isso é útil para resolver ambiguidades quando o compilador não consegue inferir o tipo alvo e para documentar intenção: `@as(u32, 255)` deixa claro que o valor é um `u32`, não um `comptime_int` genérico.

## Comparação com Outras Linguagens

Em **C**, coerções implícitas são amplas e frequentemente silenciosas, levando a bugs clássicos como truncamento de inteiros e comparações de signed/unsigned sem aviso. Em **Rust**, as coerções implícitas são mais restritas que em C, mas `as` permite conversões explícitas sem panic mesmo se houver perda de dados. Já em Zig, qualquer narrowing exige um builtin explícito, e em modo Debug essas conversões são verificadas em runtime — `@intCast` causa panic se o valor não couber no tipo destino.

```zig
// Segurança em runtime (modo Debug):
const grande: u32 = 300;
const pequeno: u8 = @intCast(grande); // PANIC: 300 não cabe em u8
```

Em `ReleaseFast`, a verificação é removida por performance — por isso é importante testar em Debug primeiro.

## Boas Práticas

- **Prefira coerções implícitas quando disponíveis**: `const s: []u8 = &array;` é mais limpo que um cast explícito.
- **Use `@intCast` com consciência**: Em modo Debug há checagem, mas em Release não. Valide os intervalos antes de converter.
- **Evite casts em cadeia**: `@intCast(@floatToInt(...))` obscurece a intenção. Faça um passo por vez com variáveis intermediárias.
- **Use `@as` para documentar**: Em contextos ambíguos, `@as(u32, valor)` torna o tipo explícito e melhora a leitura do código.

## Armadilhas Comuns

- **Comparar tipos diferentes**: `==` entre `u32` e `i32` não é permitido. Converta explicitamente primeiro.
- **Aritmética mista**: Somar `u8` com `u32` exige que ambos estejam no mesmo tipo. Use `@as` ou `@intCast`.
- **Literais negativos em unsigned**: `const x: u32 = -1;` é erro de compilação. Zig não permite conversão implícita de valor negativo para unsigned.
- **Perda de precisão float**: Converter `f64` para `f32` exige `@floatCast`, pois pode perder precisão.

## Termos Relacionados

- [comptime_int](/glossario/comptime-int/) — Tipo que pode ser coagido para qualquer inteiro
- [comptime_float](/glossario/comptime-float/) — Tipo que pode ser coagido para qualquer float
- [anytype](/glossario/anytype/) — Inferência de tipo para parâmetros genéricos
- [Pointer Types](/glossario/pointer-types/) — Coerção entre tipos de ponteiro

## Tutoriais Relacionados

- [Sistema de Tipos do Zig](/tutoriais/tipos/)
- [Conversões de Tipo em Zig](/tutoriais/conversoes/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
