Encontrar la longitud de la matriz dentro de una función [duplicate]

6 minutos de lectura

avatar de usuario
makhlaghi

En el programa debajo de la longitud de la matriz ar es correcto en main pero en temp muestra la longitud del puntero a ar que en mi computadora es 2 (en unidades de sizeof(int)).

#include <stdio.h>

void temp(int ar[]) // this could also be declared as `int *ar`
{
    printf("%d\n", (int) sizeof(ar)/sizeof(int));
}

int main(void)
{
    int ar[]={1,2,3};
    printf("%d\n", (int) sizeof(ar)/sizeof(int));
    temp(ar);
    return 0;
}

Quería saber cómo debo definir la función para que la longitud de la matriz se lea correctamente en la función.

  • Probablemente, la mejor manera de hacerlo sería agregar un parámetro adicional que tome el tamaño de la matriz, es decir void temp(int *ar, size_t len);

    – mfjones

    11 de julio de 2013 a las 9:51

  • @ Th3Cuber por lo que entiendo, quiere la longitud como resultado.

    – Adrián Jandl

    11 de julio de 2013 a las 9:52

  • Debido a que el tamaño de la computadora del operador en compilation tiempo por lo que no puede ser dinámico. tienes que pasarlo explícitamente. Leer aquí: sizeof es un operador de tiempo de compilación

    –Grijesh Chauhan

    11 de julio de 2013 a las 9:58


  • strlen() solo funciona en cadenas, no en matrices de enteros, ¿no es correcto?

    – makhlaghi

    11 de julio de 2013 a las 10:05

  • @Ishmeet strlen cuenta el número de caracteres antes de un \0no la capacidad de la matriz.

    – Weston

    11 de julio de 2013 a las 10:14

No hay una forma ‘incorporada’ de determinar la longitud dentro de la función. Sin embargo pasas arr, sizeof(arr) siempre devolverá el tamaño del puntero. Entonces, la mejor manera es pasar el número de elementos como un argumento separado. Alternativamente, podría tener un valor especial como 0 o -1 que indica el final (como si fuera \0 en cadenas, que son sólo char []). Pero, por supuesto, el tamaño de la matriz ‘lógica’ era sizeof(arr)/sizeof(int) - 1

  • ¡Esta es una sugerencia interesante! Intentaré hacerlo así. En mi programa, los valores en la matriz deben ser positivos, por lo que agregaré un valor negativo. Pero entonces el problema es este: ¿cómo puedo agregar un valor negativo al final de la matriz de antemano y sin saber cuántos elementos tiene?

    – makhlaghi

    11 de julio de 2013 a las 9:59

  • En tu ejemplo, declararías int ar[] = { 1, 2, 3, -1 };. En una situación más compleja, podría, por ejemplo, inicializar su conjunto completo con -1 en un bucle antes de llenarlo.

    –Ingo Leonhardt

    11/07/2013 a las 10:00


  • 'logical' array size was sizeof(arr)/sizeof(int) - 1 NO el tamaño de la matriz es: sizeof(arr)/sizeof(int) usar -1 para el índice más alto.

    –Grijesh Chauhan

    11 de julio de 2013 a las 10:06

  • @Grijesh por eso escribí “‘lógico'”. Pensar en strlen() donde ‘\0’ tampoco se cuenta.

    –Ingo Leonhardt

    11 de julio de 2013 a las 10:08

avatar de usuario
Marún

Cuando escribes size(ar) entonces estás pasando un puntero y no una matriz.

El tamaño de un puntero y un int es 4 u 8 – dependiendo de ITB (O, como mencionó @ H2CO3, algo completamente diferente), por lo que está obteniendo sizeof(int *)/sizeof int (4/4=1 para máquinas de 32 bits y 8/4=2 para máquinas de 64 bits), que es 1 o 2 (O… algo diferente).

Recuerde, en C, cuando pasa una matriz como argumento a una función, está pasando un puntero a una matriz.
Si desea pasar el tamaño de la matriz, debe pasarlo como un argumento separado.

  • Gracias por la explicación. Lo entiendo, solo quería ver si realmente no hay forma de hacerlo dentro de la función, sin agregar parámetros.

    – makhlaghi

    11 de julio de 2013 a las 10:01


  • @Maroun Maroun Escribí la misma respuesta primero, pero no responde, por lo tanto, la eliminé. Lea mi comentario a la pregunta.

    –Grijesh Chauhan

    11 de julio de 2013 a las 10:03

  • “El tamaño de un puntero y un int es 4 u 8”, o algo completamente diferente. Esto se puede explicar muy bien sin hacer suposiciones incorrectas.

    usuario529758

    11 de julio de 2013 a las 10:27

  • @H2CO3 Es suficiente decir que puede tener dos valores diferentes para aclarar mi punto, sin embargo, agregaré esto para que sea mejor.

    – Marún

    11 de julio de 2013 a las 10:31

  • estás pasando un puntero a una matriz.” no del todo bien. Si una matriz se pasa a una función, “decae” en un puntero a su primer elemento. Por dirección, esto es lo mismo que el puntero a la matriz, por tipo definitivamente no lo es.

    – alk

    30 de diciembre de 2017 a las 17:43

avatar de usuario
weston

No uses una función, usa una macro para esto:

//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))

int main(void)
{
    int ar[]={1,2,3};
    printf("%d\n", arrayLength(ar));
    return 0;
}

Todavía no puede usar esta macro dentro de una función como su temp donde la matriz se pasa como parámetro por las razones que otros han mencionado.

La alternativa si desea pasar un tipo de datos es definir un tipo que tenga tanto una matriz como una capacidad:

typedef struct
{
  int *values;
  int capacity;
} intArray;

void temp(intArray array)
{
  printf("%d\n", array.capacity);
}

int main(void)
{
    int ar[]= {1, 2, 3};
    intArray arr;
    arr.values = ar;
    arr.capacity = arrayLength(ar);
    temp(arr);
    return 0;
}

Esto lleva más tiempo configurarlo, pero es útil si te encuentras pasándolo por muchas funciones.

  • Gracias, pero la macro tampoco funciona en la función. Si quisiera que este trabajo se hiciera en main() no habría ningún problema desde el principio.

    – makhlaghi

    11 de julio de 2013 a las 10:07

  • @astroboy es justo, también he puesto otra sugerencia.

    – Weston

    11 de julio de 2013 a las 10:24

  • Este es un método interesante. Sin duda lo consideraré. Gracias de nuevo.

    – makhlaghi

    11 de julio de 2013 a las 10:27

Como han dicho otros, la solución obvia es pasar la longitud de la matriz como parámetro, también puede almacenar este valor al comienzo de la matriz

#include <stdio.h>

void temp(int *ar)
{
    printf("%d\n", ar[-1]);
}

int main(void)
{
    int ar[]= {0, 1, 2, 3};
    ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
    printf("%d\n", ar[0]);
    temp(ar + 1);
    return 0;
}

Necesita envolver la matriz en una estructura:

#include<stdio.h>

struct foo {int arr[5];};
struct bar {double arr[10];};

void temp(struct foo f, struct bar g)
{
    printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
    printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}

void main(void)
{
    struct foo tmp1 = {{1,2,3,4,5}};
    struct bar tmp2;
    temp(tmp1,tmp2);

    return;
}

No creo que puedas hacer esto usando una función. Siempre devolverá la longitud del puntero en lugar de la longitud de toda la matriz.

avatar de usuario
ojblass

Dentro de la función ar hay un puntero, por lo que el operador sizeof devolverá la longitud de un puntero. La única forma de calcularlo es hacer que ar sea global o cambiar su nombre. La forma más sencilla de determinar la longitud es size(array_name)/(size_of(int). La otra cosa que puede hacer es pasar este cálculo a la función.

¿Ha sido útil esta solución?