En primer lugar, aquí hay un código:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
¿Hay alguna forma de averiguar el tamaño de la matriz a la que ptr
apunta (en lugar de simplemente dar su tamaño, que es de cuatro bytes en un sistema de 32 bits)?
Respuestas:
No puedes. El compilador no sabe a qué apunta el puntero. Hay trucos, como terminar la matriz con un valor fuera de banda conocido y luego contar el tamaño hasta ese valor, pero eso no se usa
sizeof()
.Otro truco es el mencionado por Zan , que consiste en esconder el tamaño en algún lugar. Por ejemplo, si está asignando dinámicamente la matriz, asigne un bloque uno más grande que el que necesita, guarde el tamaño en la primera int y regrese
ptr+1
como el puntero a la matriz. Cuando necesite el tamaño, disminuya el puntero y mire el valor oculto. Solo recuerde liberar todo el bloque desde el principio, y no solo la matriz.fuente
La respuesta es no."
Lo que hacen los programadores de C es almacenar el tamaño de la matriz en algún lugar. Puede ser parte de una estructura, o el programador puede engañar un poco y
malloc()
más memoria de la solicitada para almacenar un valor de longitud antes del inicio de la matriz.fuente
Para las matrices dinámicas ( malloc o C ++ nuevo ) necesita almacenar el tamaño de la matriz como lo mencionan otros o tal vez construir una estructura de administrador de matriz que maneje agregar, eliminar, contar, etc. Desafortunadamente, C no hace esto tan bien como C ++ ya que básicamente tiene que compilarlo para cada tipo de matriz diferente que está almacenando, lo cual es engorroso si tiene múltiples tipos de matrices que necesita administrar.
Para las matrices estáticas, como la de su ejemplo, hay una macro común utilizada para obtener el tamaño, pero no se recomienda ya que no comprueba si el parámetro es realmente una matriz estática. Sin embargo, la macro se usa en código real, por ejemplo, en los encabezados del kernel de Linux, aunque puede ser ligeramente diferente de la siguiente:
Puede buscar en Google por razones para desconfiar de macros como esta. Ten cuidado.
Si es posible, el C ++ stdlib como vector, que es mucho más seguro y fácil de usar.
fuente
ARRAY_SIZE
macro siempre funciona si su argumento es una matriz (es decir, expresión del tipo de matriz). Para su llamada "matriz dinámica", nunca obtiene una "matriz" real (expresión del tipo de matriz). (Por supuesto, no puede hacerlo, ya que los tipos de matriz incluyen su tamaño en tiempo de compilación). Simplemente obtiene un puntero al primer elemento. Su objeción "no verifica si el parámetro es realmente una matriz estática" no es realmente válida, ya que son diferentes ya que uno es un conjunto y el otro no.Hay una solución limpia con plantillas C ++, sin usar sizeof () . La siguiente función getSize () devuelve el tamaño de cualquier matriz estática:
Aquí hay un ejemplo con una estructura foo_t :
Salida:
fuente
T (&)[SIZE]
. ¿Puedes explicar qué significa esto? También podría mencionar constexpr en este contexto.SIZE
como un argumento, es un parámetro de plantilla que tiene ser conocido por la definición de la función.)Para este ejemplo específico, sí, existe, SI usa typedefs (ver más abajo). Por supuesto, si lo hace de esta manera, puede usar SIZEOF_DAYS, ya que sabe a qué apunta el puntero.
Si tiene un puntero (void *), como lo devuelve malloc () o similar, entonces no, no hay forma de determinar a qué estructura de datos apunta el puntero y, por lo tanto, no hay forma de determinar su tamaño.
Salida:
fuente
Como han indicado todas las respuestas correctas, no puede obtener esta información solo del valor del puntero decaído de la matriz. Si el puntero decaído es el argumento recibido por la función, entonces el tamaño de la matriz de origen debe proporcionarse de alguna otra manera para que la función conozca ese tamaño.
Aquí hay una sugerencia diferente de la que se ha proporcionado hasta ahora, que funcionará: en su lugar, pase un puntero a la matriz. Esta sugerencia es similar a las sugerencias de estilo C ++, excepto que C no admite plantillas o referencias:
Pero, esta sugerencia es un poco tonta para su problema, ya que la función se define para conocer exactamente el tamaño de la matriz que se pasa (por lo tanto, hay poca necesidad de usar sizeof en la matriz). Sin embargo, lo que sí hace es ofrecer algún tipo de seguridad. Le prohibirá pasar en una matriz de un tamaño no deseado.
Si se supone que la función puede operar en cualquier tamaño de matriz, deberá proporcionar el tamaño de la función como información adicional.
fuente
No hay una solución mágica. C no es un lenguaje reflexivo. Los objetos no saben automáticamente qué son.
Pero tienes muchas opciones:
fuente
Mi solución a este problema es guardar la longitud de la matriz en una estructura Array como una metainformación sobre la matriz.
Pero debe preocuparse por establecer la longitud correcta de la matriz que desea almacenar, porque no hay forma de verificar esta longitud, como explicaron masivamente nuestros amigos.
fuente
Puedes hacer algo como esto:
fuente
No, no puede usar
sizeof(ptr)
para encontrar el tamaño de la matriz a laptr
que apunta.Aunque asignar memoria adicional (más del tamaño de la matriz) será útil si desea almacenar la longitud en espacio adicional.
fuente
Tamaño de días [] es 20, que no es de elementos * tamaño de su tipo de datos. Si bien el tamaño del puntero es 4, no importa a qué apunte. Porque un puntero apunta a otro elemento almacenando su dirección.
fuente
array_size pasa a la variable de tamaño :
El uso es:
fuente
En las cadenas hay un
'\0'
carácter al final, por lo que la longitud de la cadena se puede obtener utilizando funciones comostrlen
. El problema con una matriz de enteros, por ejemplo, es que no puede usar ningún valor como valor final, por lo que una posible solución es abordar la matriz y usar comoNULL
puntero el valor final .fuente
NULL
es probablemente la alternativa menos eficiente imaginable para almacenarsize
directamente un elemento separado . Especialmente si realmente usa esta capa adicional de indirección todo el tiempo.