---
title: "@mulWithOverflow em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@mulwithoverflow-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@mulwithoverflow-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @mulWithOverflow em Zig. Multiplicação com detecção de overflow retornando resultado e flag. Exemplos práticos pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# @mulWithOverflow em Zig — Referência e Exemplos

Referência completa do @mulWithOverflow em Zig. Multiplicação com detecção de overflow retornando resultado e flag. Exemplos práticos pt-BR.


# @mulWithOverflow em Zig

O `@mulWithOverflow` realiza uma multiplicação e indica se houve **overflow**. Retorna uma tupla com o resultado (possivelmente truncado) e um bit de overflow. Multiplicação é especialmente propensa a overflow — dois valores que cabem em u32 podem facilmente produzir resultado que não cabe.

## Sintaxe

```zig
@mulWithOverflow(a: T, b: T) struct { T, u1 }
```

## Parâmetros

- **a** (`T`): Primeiro fator (tipo inteiro).
- **b** (`T`): Segundo fator (mesmo tipo inteiro).

## Valor de retorno

Retorna uma tupla `struct { T, u1 }`:
- **[0]** (`T`): Resultado da multiplicação (truncado se overflow).
- **[1]** (`u1`): `1` se houve overflow, `0` caso contrário.

## Exemplos práticos

### Exemplo 1: Detecção de overflow na multiplicação

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

pub fn main() void {
    // Sem overflow
    const r1 = @mulWithOverflow(@as(u8, 10), @as(u8, 20));
    std.debug.print("10 * 20 = {} (overflow: {})\n", .{ r1[0], r1[1] });
    // 10 * 20 = 200 (overflow: 0)

    // Com overflow: 200 * 2 = 400, mas u8 vai até 255
    const r2 = @mulWithOverflow(@as(u8, 200), @as(u8, 2));
    std.debug.print("200 * 2 = {} (overflow: {})\n", .{ r2[0], r2[1] });
    // 200 * 2 = 144 (overflow: 1)  — 400 mod 256 = 144
}
```

### Exemplo 2: Alocação segura (verificar tamanho)

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

fn alocarMatriz(allocator: std.mem.Allocator, linhas: usize, colunas: usize) ![]f64 {
    // Verificar se linhas * colunas causa overflow
    const total = @mulWithOverflow(linhas, colunas);
    if (total[1] != 0) {
        return error.TamanhoExcessivo;
    }

    return try allocator.alloc(f64, total[0]);
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const matriz = try alocarMatriz(gpa.allocator(), 100, 100);
    defer gpa.allocator().free(matriz);

    std.debug.print("Alocado: {} elementos\n", .{matriz.len});
}
```

### Exemplo 3: Conversão de unidades com verificação

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

fn kbParaBytes(kb: u32) !u32 {
    const resultado = @mulWithOverflow(kb, @as(u32, 1024));
    if (resultado[1] != 0) return error.Overflow;
    return resultado[0];
}

fn mbParaBytes(mb: u32) !u32 {
    const kb = @mulWithOverflow(mb, @as(u32, 1024));
    if (kb[1] != 0) return error.Overflow;
    return kbParaBytes(kb[0]);
}

pub fn main() void {
    const bytes = kbParaBytes(512) catch 0;
    std.debug.print("512 KB = {} bytes\n", .{bytes});

    const grande = mbParaBytes(5000) catch |err| {
        std.debug.print("Erro: {s}\n", .{@errorName(err)});
        return;
    };
    _ = grande;
}
```

## Casos de uso comuns

1. **Alocação de memória**: Verificar se N * sizeof(T) não causa overflow antes de alocar.
2. **Conversão de unidades**: KB para bytes, minutos para milissegundos, etc.
3. **Cálculos financeiros**: Multiplicar valores monetários por quantidades.
4. **Dimensionamento de buffers**: Calcular tamanho total de matrizes/grids.

## Considerações de desempenho

Em arquiteturas modernas, `@mulWithOverflow` é compilado para uma única instrução de multiplicação seguida de verificação do carry/overflow flag. Em x86-64, isso se traduz em `imul` (para signed) ou `mul` (para unsigned) com verificação de overflow, sendo mais eficiente do que qualquer alternativa em software.

Para tipos como `usize`, o compilador usa as instruções nativas de 64 bits, sem overhead extra. O custo é essencialmente o mesmo de uma multiplicação comum, com a adição de uma instrução de verificação de flag.

## Comparação com equivalente em C

Em C, detectar overflow de multiplicação requer código manual e é propenso a erros:

```c
// C: verificação manual de overflow (frágil e verbosa)
#include <limits.h>

int multiplicar_seguro(unsigned int a, unsigned int b, unsigned int *resultado) {
    if (a != 0 && b > UINT_MAX / a) {
        return 1; // overflow
    }
    *resultado = a * b;
    return 0;
}
```

Em Zig, a detecção é direta, atômica e não requer divisão como verificação prévia:

```zig
// Zig: claro e eficiente
const resultado = @mulWithOverflow(a, b);
if (resultado[1] != 0) return error.Overflow;
return resultado[0];
```

## Erros comuns

**1. Ignorar o flag de overflow:**
```zig
// ERRADO: ignora o flag — pode produzir resultado incorreto silenciosamente
const resultado = @mulWithOverflow(a, b)[0];

// CORRETO: sempre verificar o flag
const r = @mulWithOverflow(a, b);
if (r[1] != 0) return error.Overflow;
const resultado = r[0];
```

**2. Usar tipo errado para os operandos:**
```zig
// ERRADO: mistura de tipos
// const r = @mulWithOverflow(@as(u32, a), @as(u64, b)); // erro de compilação

// CORRETO: ambos os operandos devem ter o mesmo tipo
const r = @mulWithOverflow(@as(u64, a), @as(u64, b));
```

## Perguntas Frequentes

**P: Qual é a diferença entre `@mulWithOverflow` e multiplicação com `*`?**

R: O operador `*` em modo Debug/ReleaseSafe causa panic em caso de overflow. Em ReleaseFast, resulta em undefined behavior. O `@mulWithOverflow` sempre retorna o resultado truncado junto com a flag de overflow, permitindo que o programador trate o caso explicitamente sem panic e sem undefined behavior.

**P: Posso usar `@mulWithOverflow` com tipos signed (i32, i64)?**

R: Sim. Para tipos signed, overflow ocorre quando o resultado não cabe no intervalo representável (ex: i8 vai de -128 a 127). O comportamento de wrapping segue a mesma regra de truncamento em complemento de dois.

**P: É possível usar `@mulWithOverflow` em comptime?**

R: Sim, o builtin funciona em comptime. Isso é útil para verificações estáticas de valores conhecidos em tempo de compilação, como validar constantes de configuração.

## Builtins relacionados

- [@addWithOverflow](/builtins/add-with-overflow/) — Adição com detecção de overflow
- [@subWithOverflow](/builtins/sub-with-overflow/) — Subtração com detecção de overflow
- [@shlExact](/builtins/shl-exact/) — Shift left exato (multiplicação por potência de 2)
- [@min](/builtins/min/) / [@max](/builtins/max/) — Limitar valores

## Tutoriais relacionados

- [Aritmética em Zig](/tutoriais/aritmetica-zig/)
- [Gerenciamento de Memória em Zig](/tutoriais/gerenciamento-de-memoria-zig/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
