strings resueltos matriz matrices imprimir ejercicios caracteres cadenas cadena arreglos arreglo c arrays

resueltos - ¿Hay una función estándar en C que devolvería la longitud de una matriz?



matriz de cadenas en c (6)

A menudo, la técnica descrita en otras respuestas se encapsula en una macro para que sea más fácil para los ojos. Algo como:

#define COUNT_OF( arr) (sizeof(arr)/sizeof(0[arr]))

Tenga en cuenta que la macro anterior utiliza un pequeño truco para colocar el nombre de la matriz en el operador de índice ('' [] '') en lugar del 0 : esto se hace en caso de que la macro se utilice por error en el código C ++ con un elemento que sobrecargue al operator[]() . El compilador se quejará en lugar de dar un mal resultado.

Sin embargo, también tenga en cuenta que si pasa un puntero en lugar de una matriz, la macro dará un mal resultado en silencio; este es uno de los principales problemas con el uso de esta técnica.

Recientemente comencé a usar una versión más compleja que robé del código base de Google Chromium:

#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

En esta versión, si un puntero se pasa por error como argumento, el compilador se quejará en algunos casos, específicamente si el tamaño del puntero no es divisible de manera uniforme por el tamaño del objeto al que apunta el puntero. En esa situación, una división por cero causará un error en el compilador. En realidad, al menos un compilador que he usado emite una advertencia en lugar de un error: no estoy seguro de qué genera para la expresión que tiene una división por cero.

Esa macro no cierra la puerta al usarla por error, pero está tan cerca como he visto nunca en la C recta.

Si desea una solución aún más segura para cuando esté trabajando en C ++, eche un vistazo a Compile time size of_array sin usar una macro que describa un método bastante complejo basado en plantillas que Microsoft usa en winnt.h .

¿Hay una función estándar en C que devolvería la longitud de una matriz?


El número de elementos en una matriz x se puede obtener mediante:

sizeof(x)/sizeof(x[0])

Debe tener en cuenta que las matrices, cuando se pasan a funciones, se degradan en punteros que no llevan la información de tamaño. En realidad, la información de tamaño nunca está disponible para el tiempo de ejecución, ya que se calcula en tiempo de compilación, pero puede actuar como si estuviera disponible donde la matriz es visible (es decir, donde no se ha degradado).

Cuando paso matrices a una función que necesito tratar como matrices, siempre me aseguro de que se pasen dos argumentos:

  • la longitud de la matriz; y
  • El puntero a la matriz.

Entonces, mientras que la matriz se puede tratar como una matriz donde se declara, se trata como un tamaño y un puntero en cualquier otra parte.

Tiendo a tener código como:

#define countof(x) (sizeof(x)/sizeof(x[0])) : : : int numbers[10]; a = fn (countof(numbers),numbers);

entonces fn() tendrá la información del tamaño disponible.

Otro truco que he usado en el pasado (un poco más desordenado en mi opinión, pero lo daré aquí por completo) es tener una matriz de una unión y hacer que el primer elemento tenga la longitud, algo como:

typedef union { int len; float number; } tNumber; tNumber number[10]; : : : number[0].len = 5; a = fn (number);

entonces fn() puede acceder a la longitud y a todos los elementos y no tiene que preocuparse por la dicotomía matriz / puntero.

Esto tiene la ventaja adicional de permitir que la longitud varíe (es decir, la cantidad de elementos en uso, no la cantidad de unidades asignadas). Pero tiendo a no usar esto ya que considero que la versión de matriz de dos argumentos (tamaño y datos) es mejor.


La respuesta simple, por supuesto, es no. Pero la respuesta práctica es "Necesito saberlo de todos modos", por lo tanto, analicemos los métodos para solucionar esto.

Una forma de salirse con la suya por un tiempo, como ya se mencionó un millón de veces, es con sizeof() :

int i[] = {0, 1, 2}; ... size_t i_len = sizeof(i) / sizeof(i[0]);

Esto funciona, hasta que intentamos pasar i a una función, o llevar un puntero a i . Entonces, ¿qué hay de las soluciones más generales?

La solución general aceptada es pasar la longitud de la matriz a una función junto con la matriz. Esto lo vemos mucho en la biblioteca estándar:

void *memcpy(void *s1, void *s2, size_t n);

Copiaremos n bytes desde s1 a s2 , lo que nos permitirá usar n para garantizar que nuestros búferes nunca se desborden. Esta es una buena estrategia: tiene una sobrecarga baja y, en realidad, genera un código eficiente (comparado con strcpy() , que tiene que verificar el final de la cadena y no tiene forma de "saber" cuántas iteraciones debe realizar, y strncpy() pobre, que tiene que comprobar ambas, ambas pueden ser más lentas y pueden acelerarse utilizando memcpy() si por alguna razón ya ha calculado la longitud de la cadena.

Otro enfoque es encapsular su código en una struct . El truco común es este:

typedef struct _arr { size_t len; int arr[0]; } arr;

Si queremos una matriz de longitud 5, hacemos esto:

arr *a = malloc(sizeof(*a) + sizeof(int) * 5); a->len = 5;

Sin embargo, este es un truco que solo está moderadamente bien definido (C99 le permite usar int arr[] ) y requiere bastante mano de obra. Una forma "mejor definida" de hacer esto es:

typedef struct _arr { size_t len; int *arr; } arr;

Pero entonces nuestras asignaciones (y desasignaciones) se vuelven mucho más complicadas. El beneficio de cualquiera de estos enfoques es, por supuesto, que ahora los arreglos que usted realice llevarán sus longitudes con ellos. Es un poco menos eficiente en memoria, pero es bastante seguro. Si eligió una de estas rutas, asegúrese de escribir las funciones de ayuda para que no tenga que asignar y desasignar manualmente (y trabajar con) estas estructuras.


No no hay.

Para las matrices de tamaño constante, puede usar el truco común que mencionó Andrew, sizeof(array) / sizeof(array[0]) , pero esto solo funciona en el ámbito en el que se declaró la matriz.
sizeof(array) le da el tamaño de la matriz completa, mientras que sizeof(array[0]) le da el tamaño del primer elemento.
Vea la respuesta de Michaels sobre cómo envolver eso en una macro.

Para las matrices asignadas dinámicamente, puede hacer un seguimiento del tamaño en un tipo integral o hacer que termine en 0, si es posible (es decir, asigne 1 elemento más y establezca el último elemento en 0).


Si tiene un objeto de tipo matriz, la cantidad de elementos en la matriz se puede expresar como sizeof a / sizeof *a . Si permitiste que el objeto de la matriz se descomponga al tipo de puntero (o solo tenía un objeto para comenzar), en el caso general no hay forma de determinar el número de elementos en la matriz.


sizeof array / sizeof array[0]