web-dev-qa-db-fra.com

Quelle est la taille maximale d'un tableau en C?

Je comprends que le matériel limitera la quantité de mémoire allouée pendant l'exécution du programme. Cependant, ma question est sans égard au matériel. En supposant qu'il n'y avait pas de limite à la quantité de mémoire, n'y aurait-il pas de limite au tableau?

45
Nyxm

Il n'y a pas de fixe limite à la taille d'un tableau en C.

La taille de tout objet unique, y compris de tout objet de tableau, est limitée par SIZE_MAX, la valeur maximale du type size_t, qui est le résultat de l'opérateur sizeof. (On ne sait pas très bien si la norme C autorise les objets plus gros que SIZE_MAX _ octets, mais dans la pratique, ces objets ne sont pas supportés; voir note de bas de page.) Depuis SIZE_MAX est déterminé par la mise en oeuvre et ne peut être modifié par aucun programme imposant une limite supérieure de SIZE_MAX _ octets pour un seul objet. (Il s'agit d'une limite supérieure, et non d'une moindre limite supérieure; les implémentations peuvent imposer des limites plus petites, et le font généralement.)

La largeur du type void*, un type de pointeur générique, impose une limite supérieure à la taille totale de tous les objets d'un programme en cours d'exécution (qui peut être supérieure à la taille maximale d'un objet).

La norme C impose des limites inférieures, mais pas des limites supérieures, à ces tailles fixes. Aucune implémentation C conforme ne peut prendre en charge des objets de taille infinie, mais elle peut en principe prendre en charge des objets de toute taille finie. Les limites supérieures sont imposées par les implémentations individuelles de C, par les environnements dans lesquels elles fonctionnent, et par la physique, et non par le langage.

Par exemple, une implémentation conforme pourrait avoir SIZE_MAX égal à 21024-1, ce qui signifie qu'il pourrait en principe ont des objets jusqu'à 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 octets.

Bonne chance pour trouver du matériel qui supporte réellement de tels objets.

Note de bas de page: Il n'y a pas de règle explicite qu'aucun objet ne peut être plus grand que SIZE_MAX octets. Vous ne pouvez pas utilement appliquer l'opérateur sizeof à un tel objet, mais comme tout autre opérateur, sizeof peut déborder; cela ne signifie pas que vous ne pouvez pas effectuer d'opérations sur un tel objet. Mais dans la pratique, toute mise en oeuvre saine rendra size_t assez grand pour représenter la taille de tout objet pris en charge.

42
Keith Thompson

C99 5.2.4.1 Taille minimale ("= limites de traduction")

La mise en œuvre doit pouvoir traduire et exécuter au moins un programme contenant au moins une instance de chacune des limites suivantes: 13)

  • 65535 octets dans un objet (dans un environnement hébergé uniquement)

13) Les mises en œuvre devraient éviter d'imposer des limites de traduction fixes autant que possible.

Cela suggère qu'une implémentation conforme pourrait refuser de compiler un objet (incluant les tableaux) avec plus de short octets.

PTRDIFF_MAX semble être une limite pratique pour les objets de tableau statique

La norme C99 6.5.6 Opérateurs additifs dit:

9 Lorsque deux pointeurs sont soustraits, les deux doivent pointer sur des éléments du même objet de tableau, ou d'un passé après le dernier élément de l'objet de tableau; le résultat est la différence des indices des deux éléments du tableau. La taille du résultat est définie par l'implémentation et son type (un type entier signé) est ptrdiff_t défini dans le <stddef.h> entête. Si le résultat n'est pas représentable dans un objet de ce type, le comportement est indéfini.

Ce qui implique pour moi que des tableaux plus grands que ptrdiff_t _ sont autorisés en théorie, mais vous ne pouvez pas prendre la différence d’adresses de manière portable.

Donc, peut-être que pour cette raison, GCC semble vous limiter à ptrdiff_t. Ceci est également mentionné à: Pourquoi la taille maximale d'un tableau est-elle "trop ​​grande"?

J'ai vérifié empiriquement ceci avec main.c:

#include <stdint.h>

uint8_t a[(X)];

int main(void) {
    return 0;
}

et ensuite à 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
$

Voir aussi

Un ordinateur 64 bits pourrait théoriquement traiter un maximum de 2 ^ 64 octets de mémoire.

6
greg

Sans tenir compte de la mémoire, la taille maximale d'un tableau est limitée par le type d'entier utilisé pour indexer le tableau.

4
Greg Hewgill

La taille du pointeur limitera la mémoire à laquelle vous pourrez accéder. Même si le matériel prend en charge la mémoire illimitée, si le type de données le plus volumineux que vous pouvez utiliser est 64 bits, vous ne pourrez accéder qu'à 2 ^ 64 octets de mémoire.

2
Femaref

Je suppose que le plus grand tableau théorique serait la valeur maximale de "unsigned long" (ou quel que soit le plus grand nombre entier le plus récent standard pris en charge par votre compilateur)

2
John3136

Je cherchais un moyen de déterminer la taille maximale d'un tableau. Cette question semble poser la même chose, alors je veux partager mes conclusions.

Initialement, C ne fournit aucune fonction permettant de déterminer le nombre maximal d'éléments pouvant être alloués dans un tableau lors de la compilation. En effet, cela dépend de la mémoire disponible sur la machine sur laquelle il sera exécuté.

D'autre part, j'ai constaté que les fonctions d'allocation de mémoire (calloc() et malloc()) permettent d'allouer des tableaux plus grands. De plus, ces fonctions vous permettent de gérer les erreurs d’allocation de mémoire au moment de l’exécution.

J'espère que ça t'as aidé.

0
Tony