Parámetros y argumentos

Parámetros y argumentos

Cuando hablamos de parámetros o argumentos de una función, se suelen usar ambos términos como si fueran sinónimos. Aunque son parecidos hay una diferencia sútil:

  // fmt y args son parámetros de print

  pub fn print(comptime fmt: []const u8, args: anytype) void {

  // pasamos “Hola {s}.\n” y .{“Programador”} como argumentos

  print("Hola {s}.\n", .{"Programador"});

Es muy común usar ambos de forma intercambiable, pero saber esta diferencia puede ayudar a ser más precisos a la hora de escribir y explicar el código.

        En Zig, por defecto, los parámetros de una función son inmutables: no se pueden modificar sin más. Cuando pasamos un dato a una función, ese valor se pasa por copia. Esto quiere decir que dentro del cuerpo de la función trabajamos con una copia del dato original. Los parámetros están “desvinculados” de las variables o constantes que usamos en la llamada.

En el caso de pasar estructuras grandes, el compilador, puede optimizar el paso usando una referencia interna a esos datos (un puntero) en lugar de copiar todo el contenido. Pero como programadores no sabemos si ha hecho una u otra cosa sin ver  el código máquina compilado.

Lo más importante es recordar que el parámetro que recibimos en el cuerpo de la función siempre es una copia. Incluso aunque pases un puntero recibirás una copia de ese puntero. Si tomamos la dirección en memoria de esa copia, como hacemos a continuación, debemos de tener cuidado: es una dirección local al stack de la función y deja de ser válida al salir de ella.

inc_return_ref.zig

const std = @import("std");

const print = std.debug.print;

// incrementa un valor y devuelve la dirección de memoria

// donde apunta el parámetro n_x

fn inc(n_x: *u8) *const *u8 {

    // imprimimos la dirección en n_x

    print("Dirección que llega contenida en n_x = {}\n", .{n_x});

    // imprimimos la dirección de n_x

    print("Dirección del n_x: {}\n", .{&n_x});

    print("A qué apunta n_x: {}\n", .{&n_x.*});

    // modificamos el dato apuntado por la dirección

    // contenida en n_x

    n_x.* += 1;

    return &n_x;

}

pub fn main() void {

    // variable

    var n_a: u8 = 41;

    print("Valor n_a = {}\n", .{n_a});

    // imprimimos la dirección de la variable

    print("Dirección n_x en main {}\n", .{&n_a});

    // incrementamos n_a

    const p_x = inc(&n_a);

    print("Recuperamos el puntero: {}\n", .{p_x});

    print("Pero ya da comportamiento no definido, apunta a {}\n", .{p_x.*});

    // imprimimos n_a incrementado

    print("Valor n_a = {}\n", .{n_a});

}

$ zig run inc_return_ref.zig

Valor n_a = 41

Dirección n_x en main u8@7ffdf073a808

Dirección que llega contenida en n_x = u8@7ffdf073a808

Dirección del n_x: *u8@7ffdf073a788

A qué apunta n_x: u8@7ffdf073a808

Recuperamos el puntero: *u8@7ffdf073a788

Pero ya da comportamiento no definido, apunta a u8@6570756365520000

Valor n_a = 42

Funciones y Listas
Devolver multiples valores
© 2025 Zen of Zig