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.
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
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
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.
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.
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\0
no la capacidad de la matriz.– Weston
11 de julio de 2013 a las 10:14