transpuesta - ¿Cuál es el tamaño máximo de una matriz en C?
programacion ats matrices (7)
Entiendo que el hardware limitará la cantidad de memoria asignada durante la ejecución del programa. Sin embargo, mi pregunta es sin tener en cuenta el hardware. Suponiendo que no hubiera un límite en la cantidad de memoria, ¿no habría límite para la matriz?
El tamaño del puntero limitará la memoria a la que puede acceder. Incluso si el hardware ofrece soporte para memoria ilimitada, si el tipo de datos más grande que puede usar es de 64 bits, solo podrá acceder a 2 ^ 64 bytes de memoria.
Estaba buscando una forma de determinar el tamaño máximo para una matriz. Esta pregunta parece preguntar lo mismo, así que quiero compartir mis hallazgos.
Inicialmente, C no proporciona ninguna función para determinar la cantidad máxima de elementos asignables en una matriz en tiempo de compilación. Esto se debe a que dependerá de la memoria de disponible en la máquina donde se ejecutará.
Por otro lado, he encontrado que las funciones de asignación de memoria ( calloc()
y malloc()
) permiten asignar matrices más grandes. Además, estas funciones le permiten manejar errores de asignación de memoria de tiempo de ejecución.
Espero que ayude.
No hay un límite fijo para el tamaño de una matriz en C.
El tamaño de cualquier objeto individual, incluido cualquier objeto de matriz, está limitado por SIZE_MAX
, el valor máximo de tipo size_t
, que es el resultado del operador sizeof
. (No está del todo claro si el estándar C permite objetos mayores de SIZE_MAX
bytes, pero en la práctica tales objetos no son compatibles; ver nota al pie.) Como SIZE_MAX
está determinado por la implementación y no puede ser modificado por ningún programa, eso impone un límite superior de SIZE_MAX
bytes para cualquier objeto individual. (Eso es un límite superior, no menos límite superior, 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, en estos tamaños fijos. Ninguna implementación conforme de C puede admitir objetos de tamaño infinito, pero en principio puede admitir objetos de cualquier tamaño finito. Los límites superiores son impuestos por implementaciones C individuales, por los entornos en los que operan, y por la física, no por el lenguaje.
Por ejemplo, una implantación conforme podría tener SIZE_MAX
igual a 2 1,024 -1, lo que significa que podría, en principio, tener objetos hasta 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 bytes.
Buena suerte para encontrar hardware que realmente soporte tales objetos.
Nota al pie : no existe una regla explícita de que ningún objeto puede ser más grande que SIZE_MAX
bytes. No se puede aplicar de manera útil el operador sizeof
a tal objeto, pero al igual que cualquier otro operador, sizeof
puede desbordarse; eso no significa que no puedas realizar operaciones en tal objeto. Pero en la práctica, cualquier implementación sensata hará que size_t
suficientemente grande como para representar el tamaño de cualquier objeto que admita.
Sin tener en cuenta la memoria, el tamaño máximo de una matriz está limitado por el tipo de entero utilizado para indexar la matriz.
Supongo que la mayor matriz teórica sería el valor máximo de "unsigned long" (o el número entero más grande que admita el último estándar / su compilador)
Una máquina de 64 bits teóricamente podría abordar un máximo de 2 ^ 64 bytes de memoria.
C99 5.2.4.1 Tamaño mínimo de "límites de traducción"
La implementación debe 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)
13) 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 bytes más que short
.
PTRDIFF_MAX
parece ser un límite práctico para los objetos de matriz estática
Los operadores de aditivos C99 estándar 6.5.6 dicen:
9 Cuando se restan dos punteros, ambos señalarán elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz; el resultado es la diferencia de los subíndices de los dos elementos de la matriz. El tamaño del resultado está definido por la implementación, y su tipo (un tipo de entero con signo) es
ptrdiff_t
definido en el encabezado<stddef.h>
. 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 permitidas en teoría, pero no se puede tomar la diferencia de sus direcciones portabibly.
Entonces, quizás por esta razón, GCC parece limitarlo a ptrdiff_t
. Esto también se menciona en: ¿Por qué el tamaño máximo de una matriz es "demasiado grande"?
He comprobado empíricamente esto con main.c
:
#include <stdint.h>
uint8_t a[(X)];
int main(void) {
return 0;
}
y luego en Ubunbu 17.10:
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ printf ''
> #include <stdint.h>
> PTRDIFF_MAX
> SIZE_MAX
> '' | arm-linux-gnueabi-cpp | tail -n2
(2147483647)
(4294967295U)
$ PTRDIFF_MAX == 2147483647 == 2^31 - 1
$
$ # 2lu << 30 == 2^31 == PTRDIFF_MAX + 1
$ arm-linux-gnueabi-gcc -std=c99 -DX=''(2lu << 30)'' main.c
a.c:5:9: error: size of array ‘a’ is too large
uint8_t a[(X)];
^
$
$ # PTRDIFF_MAX
$ arm-linux-gnueabi-gcc -std=c99 -DX=''(2lu << 30) - 1lu'' main.c
$
Ver también