← Volver al listado de tecnologías

Tipos y Variables en Zig

Por: Artiko
zigtiposvariablesconstantes

Tipos y Variables

Variables y Constantes

En Zig, las variables se declaran con var y las constantes con const:

const std = @import("std");

pub fn main() void {
    // Constante - no puede cambiar
    const pi: f64 = 3.14159;

    // Variable - puede cambiar
    var contador: i32 = 0;
    contador += 1;

    // Inferencia de tipos
    const mensaje = "Hola"; // tipo: *const [4:0]u8
    var numero = @as(i32, 42); // tipo: i32

    std.debug.print("Pi: {d}, Contador: {d}\n", .{ pi, contador });
}

Tipos Enteros

Zig ofrece control preciso sobre el tamaño de enteros:

TipoBitsRango
i88-128 a 127
u880 a 255
i1616-32,768 a 32,767
u16160 a 65,535
i3232-2^31 a 2^31-1
u32320 a 2^32-1
i6464-2^63 a 2^63-1
u64640 a 2^64-1
isizearchPuntero con signo
usizearchPuntero sin signo
const byte: u8 = 255;
const entero: i32 = -42;
const grande: u64 = 18_446_744_073_709_551_615;
const tamanio: usize = @sizeOf(i32); // 4

Tipos Flotantes

const f16_val: f16 = 1.5;    // Media precisión
const f32_val: f32 = 3.14;   // Precisión simple
const f64_val: f64 = 2.718;  // Doble precisión
const f128_val: f128 = 1.0;  // Precisión cuádruple

Booleanos

const verdadero: bool = true;
const falso: bool = false;

// Operaciones lógicas
const y = verdadero and falso;  // false
const o = verdadero or falso;   // true
const no = !verdadero;          // false

Caracteres y Strings

// Carácter (u8)
const letra: u8 = 'A';
const unicode: u21 = '中';

// String literal (puntero a array de bytes)
const saludo: []const u8 = "Hola mundo";

// String con terminador null (para interop con C)
const c_string: [*:0]const u8 = "Hola C";

Optional Types

Los optionals pueden contener un valor o null:

const std = @import("std");

fn encontrar(haystack: []const u8, needle: u8) ?usize {
    for (haystack, 0..) |char, index| {
        if (char == needle) return index;
    }
    return null;
}

pub fn main() void {
    const texto = "Hola";

    // Usando optional
    if (encontrar(texto, 'o')) |indice| {
        std.debug.print("Encontrado en: {d}\n", .{indice});
    } else {
        std.debug.print("No encontrado\n", .{});
    }

    // Valor por defecto con orelse
    const pos = encontrar(texto, 'x') orelse 999;
    std.debug.print("Posición: {d}\n", .{pos});
}

Undefined y Null

// undefined - valor no inicializado (úsalo con cuidado)
var buffer: [100]u8 = undefined;

// null - para tipos optional
var opcional: ?i32 = null;
opcional = 42;

Coerción de Tipos

const std = @import("std");

pub fn main() void {
    // Cast explícito con @as
    const a: i32 = 10;
    const b: i64 = @as(i64, a);

    // @intCast para enteros
    const c: u8 = @intCast(a);

    // @floatFromInt para int a float
    const d: f32 = @floatFromInt(a);

    // @intFromFloat para float a int
    const e: f64 = 3.7;
    const f: i32 = @intFromFloat(e); // 3

    std.debug.print("b={d}, c={d}, d={d}, f={d}\n", .{ b, c, d, f });
}

Testing de Tipos

const std = @import("std");
const testing = std.testing;

fn duplicar(n: i32) i32 {
    return n * 2;
}

fn dividir(a: f64, b: f64) ?f64 {
    if (b == 0) return null;
    return a / b;
}

test "duplicar enteros" {
    try testing.expectEqual(@as(i32, 10), duplicar(5));
    try testing.expectEqual(@as(i32, -4), duplicar(-2));
    try testing.expectEqual(@as(i32, 0), duplicar(0));
}

test "división con optional" {
    // División normal
    const resultado = dividir(10.0, 2.0);
    try testing.expect(resultado != null);
    try testing.expectEqual(@as(f64, 5.0), resultado.?);

    // División por cero
    const div_cero = dividir(10.0, 0.0);
    try testing.expect(div_cero == null);
}

test "coerción de tipos" {
    const entero: i32 = 100;
    const flotante: f64 = @floatFromInt(entero);

    try testing.expectEqual(@as(f64, 100.0), flotante);
}

test "tamaño de tipos" {
    try testing.expectEqual(@as(usize, 1), @sizeOf(u8));
    try testing.expectEqual(@as(usize, 4), @sizeOf(i32));
    try testing.expectEqual(@as(usize, 8), @sizeOf(f64));
}

test "valores límite" {
    const max_u8: u8 = std.math.maxInt(u8);
    const min_i8: i8 = std.math.minInt(i8);

    try testing.expectEqual(@as(u8, 255), max_u8);
    try testing.expectEqual(@as(i8, -128), min_i8);
}

Ejecuta los tests:

zig test 02-tipos-variables.zig
# All 5 tests passed.

Comptime Types

Zig permite tipos determinados en tiempo de compilación:

fn crearArray(comptime T: type, comptime size: usize) [size]T {
    return [_]T{0} ** size;
}

test "comptime array" {
    const arr = crearArray(i32, 5);
    try std.testing.expectEqual(@as(usize, 5), arr.len);
}

Ejercicios

  1. Crea una función que convierta temperatura de Celsius a Fahrenheit
  2. Implementa una función que encuentre el máximo entre dos números con tests
  3. Crea un tipo optional que represente un resultado de búsqueda

Resumen