jkidv
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 manera de averiguar el tamaño de la matriz que ptr
está apuntando (en lugar de simplemente dar su tamaño, que es de cuatro bytes en un sistema de 32 bits)?
zan lince
La respuesta es no.”
Lo que hacen los programadores de C es almacenar el tamaño de la matriz en alguna parte. Puede ser parte de una estructura, o el programador puede hacer un poco de trampa y malloc()
más memoria de la solicitada para almacenar un valor de longitud antes del inicio de la matriz.
-
Así es como se implementan las cadenas de pascal.
– dsm
29 de enero de 2009 a las 16:44
-
¡y aparentemente las cadenas de pascal son la razón por la que Excel se ejecuta tan rápido!
– Adam Naylor
14 de julio de 2010 a las 19:48
-
@Adam: Es rápido. Lo uso en una lista de implementación de cadenas mías. Es súper rápido para la búsqueda lineal porque es: cargar tamaño, precargar pos+tamaño, comparar tamaño con tamaño de búsqueda, si es igual a strncmp, pasar a la siguiente cadena, repetir. Es más rápido que la búsqueda binaria hasta unas 500 cadenas.
– Zan Lince
14 de julio de 2010 a las 19:52
-
Su código está lleno de comentarios, pero creo que haría todo más fácil si agregara una explicación general de cómo funciona esto fuera del código, como texto normal. ¿Puedes editar tu pregunta y hacerlo? ¡Gracias!
– Fabio dice Reincorporar a Mónica
11 de marzo de 2017 a las 12:16
-
Creando una matriz de punteros a cada elemento para que pueda buscarlo linealmente
NULL
es probablemente la alternativa menos eficiente imaginable a simplemente almacenar unasize
directamente. Especialmente si en realidad usar esta capa adicional de indirección todo el tiempo.– Peter Cordes
19 de junio de 2018 a las 3:03
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#define array(type) struct { size_t size; type elem[0]; }
void *array_new(int esize, int ecnt)
{
size_t *a = (size_t *)malloc(esize*ecnt+sizeof(size_t));
if (a) *a = ecnt;
return a;
}
#define array_new(type, count) array_new(sizeof(type),count)
#define array_delete free
#define array_foreach(type, e, arr) \
for (type *e = (arr)->elem; e < (arr)->size + (arr)->elem; ++e)
int main(int argc, char const *argv[])
{
array(int) *iarr = array_new(int, 10);
array(float) *farr = array_new(float, 10);
array(double) *darr = array_new(double, 10);
array(char) *carr = array_new(char, 11);
for (int i = 0; i < iarr->size; ++i) {
iarr->elem[i] = i;
farr->elem[i] = i*1.0f;
darr->elem[i] = i*1.0;
carr->elem[i] = i+'0';
}
array_foreach(int, e, iarr) {
printf("%d ", *e);
}
array_foreach(float, e, farr) {
printf("%.0f ", *e);
}
array_foreach(double, e, darr) {
printf("%.0lf ", *e);
}
carr->elem[carr->size-1] = '\0';
printf("%s\n", carr->elem);
return 0;
}
Tᴏᴍᴇʀ Wᴏʟʙᴇʀɢ
Puedes hacer algo como esto:
int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;
Pedro Mortensen
Para arreglos dinámicos (malloc o C++ nuevo) necesita almacenar el tamaño de la matriz como lo mencionaron otros o tal vez construir una estructura de administrador de matrices que maneje agregar, eliminar, contar, etc. Desafortunadamente, C no hace esto tan bien como C ++, ya que básicamente tiene que construirlo para cada tipo de matriz diferente que está almacenando, lo cual es engorroso si tiene varios tipos de matrices que necesita administrar.
Para matrices estáticas, como la de su ejemplo, se usa una macro común para obtener el tamaño, pero es no recomendado ya que no verifica 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 a la siguiente:
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", ARRAY_SIZE(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Puede buscar en Google por razones para desconfiar de macros como esta. Ten cuidado.
Si es posible, el stdlib de C++ como vector, que es mucho más seguro y fácil de usar.
-
ARRAY_SIZE es un paradigma común utilizado por programadores prácticos en todas partes.
– SanjayaR
29 de enero de 2009 a las 17:19
-
Sí, es un paradigma común. Sin embargo, aún debe usarlo con precaución, ya que es fácil de olvidar y usarlo en una matriz dinámica.
– Ryan
29 de enero de 2009 a las 17:27
-
Sí, buen punto, pero la pregunta que se hizo fue sobre el puntero, no el de matriz estática.
–Paul Tomblin
29 de enero de 2009 a las 17:40
-
Ese
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, ya que los tipos de matriz incluyen su tamaño en tiempo de compilación). Solo 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 una es una matriz y la otra no.– nueva cuenta
28 de febrero de 2013 a las 18:52
-
Hay una función de plantilla flotando que hace lo mismo pero evitará el uso de punteros.
– Natalia Adams
23 de abril de 2013 a las 2:24
Siempre he usado paréntesis con sizeof; seguro que hace que parezca una llamada de función, pero creo que es más claro.
–Paul Tomblin
29 de enero de 2009 a las 16:44
¿Por qué no? ¿Tienes algo en contra de los paréntesis superfluos? Creo que se lee un poco más fácilmente con ellos, yo mismo.
–David Thornley
29 de enero de 2009 a las 16:44
@Paul: bueno… suponiendo que el lado izquierdo de esa llamada sea un puntero a int, lo escribiría como int *ptr = malloc(4 * sizeof *ptr); que para mí es mucho más claro. Menos paréntesis para leer y llevar la constante literal al frente, como en matemáticas.
– relajarse
29 de enero de 2009 a las 17:32
@unwind: ¡no asigne una serie de punteros cuando se refiere a una serie de enteros!
–Paul Tomblin
29 de enero de 2009 a las 17:47
Aquí no hay un “puntero que apunte a una matriz”. Solo un puntero que apunta a un int.
– nueva cuenta
28 de febrero de 2013 a las 19:01