2010-10-12 6 views
3

Je voulais déclarer un très grand tableau. j'ai trouvé que la taille maximale d'un tableau est size_t, qui est défini comme UINT_MAXdéclarant le plus grand tableau en utilisant size_t

donc je l'ai écrit le code comme celui-ci

int arr[UINT_MAX]; 

quand je compile cela, il dit débordement dans la dimension du tableau

mais quand j'écris comme ceci

size_t s = UINT_MAX; 
int arr[s]; 

il compile correctement. quelle est la différence

+1

Quel compilateur est-ce? FYI avec 'const' sur' size_t', les deux échouent dans Visual C++ v10 avec "la taille totale du tableau ne doit pas dépasser 0x7fffffff bytes" –

+1

"J'ai trouvé que la taille maximale d'un tableau est size_t" - c'est incorrect, 'size_t 'n'est pas une constante, c'est un type (un' typedef' pour un type de données non signé). Le type de données sous-jacent réel dépend de la plateforme. Vous pouvez utiliser 'std :: numeric_limits :: max()' pour obtenir la valeur maximale pouvant être conservée dans une variable de type 'size_t'. – Praetorian

+0

Et vos deux extraits de code produisent cette erreur sur Visual Studio 2005: «erreur C2148: la taille totale du tableau ne doit pas dépasser 0x7fffffff octets» – Praetorian

Répondre

14

Première erreur: size_t est pas nécessairement unsigned int, donc sa valeur maximale peut être différent de celui des unsigned int (UINT_MAX); de plus, en C++ pour obtenir des informations sur les limites d'un type, vous devez utiliser std::numeric_limits.

#include <limits> 

size_t s=std::numeric_limits<size_t>::max(); 

Deuxième erreur: vous n'obtiendrez jamais un tableau si gros; puisque size_t est nécessaire pour pouvoir exprimer la plus grande taille de n'importe quel objet, il devrait probablement être assez grand pour exprimer un objet grand comme l'espace d'adressage disponible à l'application, mais essayer d'allouer un tel objet nécessiterait espace d'adressage à lui, qui est infaisable; en outre, vous demandez un tableau de int s gros, ce qui signifie que ce sera UINT_MAX*sizeof(int) octets grand, ce qui sera probablement environ 4 fois l'espace d'adressage entier - clairement absurde - et d'ailleurs sizeof(arr) ne serait pas en mesure de exprimer la taille d'un tel objet, et en général les pointeurs ne pourraient même pas atteindre le sommet de ce tableau. Le compilateur détecte ces fautes et vous empêche de le faire. De plus, je déduis que vous essayez d'allouer cette chose sur la pile, qui est généralement beaucoup plus petite que toute la mémoire que l'application peut utiliser, et en général ce n'est pas une bonne idée d'y allouer de gros tableaux (vous devriez utiliser le tas pour cela). Troisième erreur: allouer toute cette mémoire n'a pas de sens.

Si vous avez besoin de beaucoup de mémoire, vous devez allouer des choses sur le tas, pas sur la pile, et allouer juste la mémoire dont vous avez besoin pour bien jouer avec le système d'exploitation et les autres applications (cette dernière considération ne s'applique pas si vous travaillez sur les systèmes embarqués où vous êtes la seule application en cours d'exécution).

Le deuxième extrait de C++ ne devrait même pas fonctionner, puisque, si cette chose est allouée sur la pile, vous allez non standard, puisqu'il s'agirait d'un VLA (disponible en C99 mais fortement rejeté du courant et du prochain standard C++). Cependant, dans ce cas, le code pour allouer ce tableau est utilisé au moment de l'exécution (les VLA en général ne sont pas fixés en dimensions), donc la vérification du compilateur n'est pas évidente à faire (bien que je suppose que optimiseur, qui, si la sémantique VLA n'est pas différente des tableaux réguliers, pourrait optimiser le VLA et essayer de faire un tableau régulier => qui échouerait pour les mêmes raisons que j'ai indiquées). Longue histoire courte: cela n'a aucun sens d'allouer toute cette mémoire (que vous ne pouviez même pas adresser), surtout sur la pile. Utilisez le tas et allouez juste ce dont vous avez besoin. Si vous avez des besoins particuliers, vous devez étudier les fonctions de mémoire virtuelle spéciales fournies par votre système d'exploitation.

+0

+1 pour mentionner la taille généralement plus petite de la pile. –

0
size_t s = UINT_MAX; 
int arr[s]; 

ne compilera pas à moins que vous déclariez s const. Notez également que UINT_MAX est la taille potentiellement la plus grande du tableau. Pratiquement, il ne vous permettra pas de déclarer un tableau de plus de quelques millions d'exemplaires. C'est parce que statique et automatique et toute la mémoire est limitée

0
size_t s = UINT_MAX; 
int arr[s]; 

signifie que arr est un tableau de longueur variable (VLA). Je pense que ce n'est pas autorisé par norme C++. Je me attends un avertissement si compilé avec

g++ -ansi -pedantic -std=c++98 

Aussi, pense, arr besoins UINT_MAX * sizeof(int) nombre d'octets. C'est assez grand!

+0

g ++ compilateur permet vla. c99 le permet aussi. – ameen

+0

Vous avez raison. Je soupçonne que le compilateur permet aux fonctionnalités C99 de se faufiler, mais ce n'est pas un code portable. –

+0

vous voyez, ce fut mon point dans ce fil http://stackoverflow.com/questions/3916608/how-important-is-standards-compliance - normes de fidélité serait formidable pour les apprenants :))) –

0

Quel compilateur utilisez-vous? Sur VC++, j'obtiens une erreur dans les deux cas (après avoir corrigé s pour être const). Même si elle compilait, il en résulterait un comportement indéfini car UINT_MAX * sizeof(int) ne rentrerait certainement pas dans l'espace d'adressage de votre processus, et de plus la valeur entière elle-même déborderait et entraînerait une valeur incorrecte pour la taille.

+0

J'ai utilisé le compilateur g ++ – ameen

+0

Avez-vous essayé d'exécuter le programme? – casablanca

2

Vous retardez l'erreur.

Vous demandez environ 16 Go * de mémoire contiguë dans les deux cas, ce qui est impossible sur une machine 32 bits.

Votre première tentative est de coder en dur la taille, et votre compilateur a été assez gentil pour vous dire à l'avance qu'il ne réussira pas.

Votre deuxième tentative utilise une variable pour la taille, qui a contourné l'avertissement du compilateur, mais elle échouera quand vous tenterez d'exécuter le programme.

* Sur les architectures typiques

+0

Vous voulez dire 4 Go de mémoire. –

+1

'UINT_MAX' est généralement d'environ 4 milliards, et un' int' est de 4 octets. 4 milliards de fois 4 octets est de 16 Go. –

+0

@Peter: Un 'int' n'est pas nécessairement 4 octets. – GManNickG

0

Pour chaque type intégral non signé, le maximum doit être représenté par -1. Par exemple, sur un système 64 bits, le code suivant

unsigned char uchar_max = -1; 
printf("%u\n", uchar_max); 
unsigned int uint_max = -1; 
printf("%u\n", uint_max); 
unsigned long ulong_max = -1; 
printf("%lu\n", ulong_max); 
size_t sizet_max = -1; 
printf("%lu\n", sizet_max); 

retours:

255 
4294967295 
18446744073709551615 
18446744073709551615 
Questions connexes