Es imprescindible comprender el código de forma correcta previamente a utilizarlo a tu proyecto si tquieres aportar algo puedes dejarlo en los comentarios.
Solución:
No hay reparado limitar el tamaño de un array C ª.
El tamaño de cualquier objeto individual, incluso de cualquier array objeto, está limitado por SIZE_MAX
el valor máximo de tipo size_t
que es el resultado de la sizeof
operador. (No está del todo claro si el estándar C permite objetos más grandes que SIZE_MAX
bytes, pero en la práctica tales objetos no son compatibles; ver nota al pie.) Dado que SIZE_MAX
está determinado por la implementación, y no puede ser modificado por ningún programa, que impone un límite superior de SIZE_MAX
bytes para cualquier objeto individual. (Ese es un límite superior, no un límite superior mínimo; las implementaciones pueden, y normalmente lo hacen, imponer límites más pequeños).
El ancho del tipo void*
un tipo de puntero genérico, impone un límite superior al tamaño total de todos los objetos en un programa en ejecución (que puede ser mayor que el tamaño máximo de un solo objeto).
El estándar C impone límites inferiores, pero no superiores, a estos tamaños fijos. Ninguna implementación C conforme puede admitir objetos de tamaño infinito, pero en principio puede admitir objetos de cualquier tamaño finito. Los límites superiores los imponen las implementaciones individuales de C, los entornos en los que operan y la física, no el lenguaje.
Por ejemplo, una implementación conforme podría tener SIZE_MAX
igual a 21024-1, lo que significa que podría en principio tener objetos hasta 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 bytes.
Buena suerte para encontrar hardware que realmente admita tales objetos.
Nota: No existe una regla explícita de que ningún objeto puede ser más grande que SIZE_MAX
bytes No podrías aplicar de manera útil el sizeof
operador a tal objeto, pero como cualquier otro operador, sizeof
puede desbordarse; eso no significa que no pueda realizar operaciones en dicho objeto. Pero en la práctica, cualquier implementación sensata hará size_t
lo suficientemente grande como para representar el tamaño de cualquier objeto que soporte.
C99 5.2.4.1 “Límites de traducción” tamaño mínimo
La implementación deberá poder traducir y ejecutar al menos un programa que contenga al menos una instancia de cada uno de los siguientes límites: 13)
- 65535 bytes en un objeto (solo en un entorno alojado)
- Las implementaciones deben evitar imponer límites de traducción fijos siempre que sea posible.
Esto sugiere que una implementación conforme podría negarse a compilar un objeto (que incluye matrices) con más de short
bytes
PTRDIFF_MAX
también impone algunos límites array dice
El estándar C99 6.5.6 Operadores aditivos dice:
9 Cuando se resten dos punteros, ambos apuntarán a elementos del mismo array objeto, o uno más allá del último elemento del array objeto; el resultado es la diferencia de los subíndices de los dos array elementos. El tamaño del resultado está definido por la implementación y su tipo (un tipo entero con signo) es
ptrdiff_t
definido en elencabezamiento. Si el resultado no es representable en un objeto de ese tipo, el comportamiento no está definido.
Lo que implica para mí que las matrices más grandes que ptrdiff_t
están permitidos en teoría, pero entonces no puede tomar la diferencia de sus direcciones de forma portátil.
Entonces, tal vez por esta razón, GCC parece limitarlo a ptrdiff_t
. Esto también se menciona en: ¿Por qué el tamaño máximo de un array “demasiado grande”?
Experimentos
Tal vez lo que importa en última instancia es lo que acepte su compilador, así que aquí vamos:
C Principal
#include
TYPE a[(NELEMS)];
int main(void)
return 0;
tallas.c
#include
#include
int main(void)
printf("PTRDIFF_MAX 0x%jxn", (uintmax_t)PTRDIFF_MAX);
printf("SIZE_MAX 0x%jxn", (uintmax_t)SIZE_MAX);
return 0;
Y luego tratamos de compilar con:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o sizes.out sizes.c
./sizes.out
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out
-DNELEMS='((2lu << 62) - 1)' -DTYPE=uint8_t main.c
Resultados:
-
PTRDIFF_MAX: 0x7fffffffffffffff = 2^63 - 1
-
TAMAÑO_MAX: 0xffffffffffffffff = 2^64 - 1
-
-DNELEMS='((2lu << 62) - 1)' -DTYPE=uint8_t
: compila (== 2^63 - 1). Ejecutarlo segfaults inmediatamente en mi mero sistema de RAM de 32 GB :-) -
-DNELEMS='(2lu << 62)' -DTYPE=uint8_t
: la compilación falla con:error: size of array ‘a’ is too large
-
-DNELEMS='(2lu << 62 - 1)' -DTYPE=uint16_t
: la compilación falla con:error: size ‘18446744073709551614’ of array ‘a’ exceeds maximum object size ‘9223372036854775807’
donde
9223372036854775807 == 0x7fffffffffffffff
Entonces, de esto entendemos que GCC impone dos limitaciones con diferentes mensajes de error:
- el número de elementos no puede exceder 2^63 (pasa a == PTRDIFF_MAX)
- array el tamaño no puede exceder 2^63 (también sucede con == PTRDIFF_MAX)
Probado en Ubuntu 20.04 amd64, GCC 9.3.0.
Ver también
- ¿Existen limitaciones de tamaño para las estructuras C?
- ¿Cuál es el tipo correcto para array índices en C?
En teoría, una máquina de 64 bits podría abordar un máximo de 2^64 bytes de memoria.
Comentarios y valoraciones
Te invitamos a defender nuestro análisis fijando un comentario y valorándolo te lo agradecemos.