Saltar al contenido

Pasando un 2D array a una función de C ++

Nuestro grupo de redactores ha estado por horas buscando para dar soluciones a tus interrogantes, te brindamos la soluciones y deseamos que resulte de mucha apoyo.

Solución:

Hay tres formas de pasar un 2D array a una función:

  1. El parámetro es un 2D array

    int array[10][10];
    void passFunc(int a[][10])
    
        // ...
    
    passFunc(array);
    
  2. El parámetro es un array que contiene punteros

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    
        // ...
    
    passFunc(array);
    
  3. El parámetro es un puntero a un puntero

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    
        // ...
    
    passFunc(array);
    

Tamaño fijo

1. Pasar por referencia

template 
void process_2d_array_template(int (&array)[rows][cols])

    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << 't';
        std::cout << std::endl;
    

En C ++ pasando el array por referencia sin perder la información de la dimensión es probablemente la más segura, ya que uno no necesita preocuparse de que la persona que llama pase una dimensión incorrecta (el compilador marca cuando no coincide). Sin embargo, esto no es posible con matrices dinámicas (de almacenamiento gratuito); funciona solo para matrices automáticas (normalmente apiladas), es decir, la dimensionalidad debe conocerse en el momento de la compilación.

2. Pasar por puntero

void process_2d_array_pointer(int (*array)[5][10])

    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << 't';
        std::cout << std::endl;
        

El equivalente en C del método anterior es pasar el array por puntero. Esto no debe confundirse con pasar por el arraytipo de puntero deteriorado (3), que es el método común y popular, aunque menos seguro que éste pero más flexible. Igual que (1), utilice este método cuando todas las dimensiones del array es fijo y conocido en tiempo de compilación. Tenga en cuenta que al llamar a la función arrayse debe pasar la dirección process_2d_array_pointer(&a) y no la dirección del primer elemento por decaimiento process_2d_array_pointer(a).

Tamaño variable

Estos se heredan de C pero son menos seguros, el compilador no tiene forma de verificar, lo que garantiza que el llamador está pasando las dimensiones requeridas. La función solo se basa en lo que la persona que llama transmite como dimensión (es). Estos son más flexibles que los anteriores, ya que invariablemente se les pueden pasar matrices de diferentes longitudes.

Debe recordarse que no existe tal cosa como pasar un array directamente a una función en C [while in C++ they can be passed as a reference (1)]; (2) está pasando un puntero al array y no el array sí mismo. Siempre pasando un array tal cual se convierte en una operación de copia de puntero que es facilitada por arrayla naturaleza de descomponerse en un puntero.

3. Pase por (valor) un puntero al tipo deteriorado

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)

    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << 't';
        std::cout << std::endl;
    

A pesar de que int array[][10] está permitido, no lo recomendaría por encima de la sintaxis anterior, ya que la sintaxis anterior deja en claro que el identificador array es un puntero único a un array de 10 enteros, mientras que esta sintaxis aspecto como si fuera un 2D array pero es el mismo puntero a un array de 10 enteros. Aquí conocemos el número de elementos en una sola fila (es decir, el tamaño de la columna, 10 aquí) pero el número de filas se desconoce y, por lo tanto, debe pasarse como argumento. En este caso, hay algo de seguridad ya que el compilador puede marcar cuando un puntero a un array con la segunda dimensión no igual a 10 se pasa. La primera dimensión es la parte variable y se puede omitir. Vea aquí la justificación de por qué solo se permite omitir la primera dimensión.

4. Pase el puntero a un puntero

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)

    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << 't';
        std::cout << std::endl;
    

De nuevo, hay una sintaxis alternativa de int *array[10] que es lo mismo que int **array. En esta sintaxis el [10] se ignora ya que se descompone en un puntero convirtiéndose en int **array. Tal vez sea solo una señal para la persona que llama que el array debe tener al menos 10 columnas, incluso entonces se requiere el recuento de filas. En cualquier caso, el compilador no marca ninguna violación de longitud / tamaño (solo verifica si el tipo pasado es un puntero a puntero), por lo tanto, requerir tanto el recuento de filas como de columnas como parámetro tiene sentido aquí.

Nota:(4) es la opción menos segura ya que apenas tiene cheque de tipo y lo más inconveniente. Uno no puede pasar legítimamente un 2D array a esta función; C-FAQ condena la solución habitual de hacer int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10); ya que potencialmente puede conducir a un comportamiento indefinido debido a array aplastamiento. La forma correcta de pasar un array en este método nos lleva a la parte inconveniente, es decir, necesitamos un adicional (sustituto) array de punteros con cada uno de sus elementos apuntando a la fila respectiva de la real, a-pasar array; este sustituto luego se pasa a la función (ver más abajo); todo esto para hacer el mismo trabajo que los métodos anteriores, que son más seguros, más limpios y quizás más rápidos.

Aquí hay un programa de controlador para probar las funciones anteriores:

#include 

// copy above functions here

int main()

    int a[5][10] =    ;
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    
        b[i] = a[i];
    
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**

Una modificación a la primera sugerencia de shengy, puede usar plantillas para hacer que la función acepte un formato multidimensional. array variable (en lugar de almacenar una array de punteros que deben administrarse y eliminarse):

template 
void func(double (&arr)[size_x][size_y])

    printf("%pn", &arr);


int main()

    double a1[10][10];
    double a2[5][5];

    printf("%pn%pnn", &a1, &a2);
    func(a1);
    func(a2);

    return 0;

Las declaraciones de impresión están ahí para mostrar que las matrices se pasan por referencia (mostrando las direcciones de las variables)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *