La limite SIZE_MAX / 2 provient des définitions de size_t et ptrdiff_t de votre implémentation, qui choisissent que les types ptrdiff_t et size_t aient la même largeur.
C Mandats standard 1 que le type size_t est non signé et que le type ptrdiff_t est signé.
Le résultat de la différence entre deux pointeurs sera toujours 2 sont de type ptrdiff_t. Cela signifie que, dans votre implémentation, la taille de l'objet doit être limitée à PTRDIFF_MAX, sinon une différence valide entre deux pointeurs ne pourrait pas être représentée dans le type ptrdiff_t, ce qui entraînerait un comportement indéfini.
La valeur SIZE_MAX / 2 est donc égale à la valeur PTRDIFF_MAX. Si l'implémentation choisit de fixer la taille maximale de l'objet à SIZE_MAX, la largeur du type ptrdiff_t devra être augmentée. Mais il est beaucoup plus facile de limiter la taille maximale de l'objet à SIZE_MAX / 2 que de faire en sorte que le type ptrdiff_t ait une plage positive supérieure ou égale à celle du type size_t.
L'offre standard est la suivante 3 commentaires 4 sur le sujet.
(Extrait de la norme ISO/IEC 9899:201x)
1 (7.19 Définitions communes 2)
Les types sont les suivants
ptrdiff_t
qui est le type d'entier signé du résultat de la soustraction de deux pointeurs ;
size_t
qui est le type d'entier non signé du résultat de l'opérateur sizeof ;
2 (6.5.6 Opérateurs additifs 9)
Lorsque deux pointeurs sont soustraits, ils doivent tous deux pointer sur des éléments du même tableau, ou l'un après le dernier élément du tableau ; le résultat est la différence entre les indices des indices des deux éléments du tableau. La taille du résultat est définie par l'implémentation, et son type (un entier signé) est ptrdiff_t défini dans l'en-tête. Si le résultat n'est pas représentable dans un objet de ce type, le comportement est indéfini.
3 (K.3.4 Types de nombres entiers 3)
Des tailles d'objets extrêmement grandes sont souvent le signe que la taille d'un objet a été calculée incorrecte. Par exemple, les nombres négatifs apparaissent comme de très grands nombres positifs lorsqu'ils sont convertis en un type non signé comme size_t. De plus, certaines implémentations ne prennent pas en charge des objets aussi grands que la valeur maximale pouvant être représentée par le type size_t.
4 (K.3.4 Types de nombres entiers 4)
Pour ces raisons, il est parfois utile de restreindre la gamme des tailles d'objets à détecter. des erreurs de programmation. Pour les implémentations visant des machines avec de grands espaces d'adressage, il est recommandé de définir RSIZE_MAX comme la plus petite taille de l'objet le plus grand supporté ou (SIZE_MAX >> 1), même si cette limite est plus petite que la taille de l'objet plus grand objet pris en charge ou (SIZE_MAX >> 1), même si cette limite est inférieure à la taille de certains objets légitimes, mais très grands. de certains objets légitimes, mais très volumineux. Les implémentations ciblant des machines avec de petits peuvent souhaiter définir RSIZE_MAX comme SIZE_MAX, ce qui signifie qu'il n'y a pas de taille d'objet qui soit considérée comme une violation des contraintes d'exécution.
13 votes
Un tableau de taille
SIZE_MAX
consomme probablement toute la mémoire.1 votes
@PaulOgilvie Alors pourquoi ont-ils choisi un nombre qui est trop grand pour l'implémentation donnée ?
0 votes
J'ai essayé et bizarrement,
typedef uint8_t array_t [SIZE_MAX/2];
compile bien0 votes
@MarkPlotnick Non... les indices des tableaux doivent être de type
size_t
ySIZE_MAX
est la valeur maximale d'une telle variable. Il n'est pas possible de déclarer des tableaux de longueur nulle ou négative.0 votes
@samgak Mais il s'avère que
typedef uint8_t array_t [SIZE_MAX/2+1];
ne compile pas, voir l'édition ci-dessus. Il semble que ce soit un bug de Mingw pour autant que je puisse en juger.1 votes
Selon le CCG code source la limite est appliquée par la contrepartie signée de
sizetype
(INT_MAX
dans le commentaire est trompeur).index
est affecté avecc_common_signed_type (sizetype);
à la ligne 5933. Cela explique probablement le problème de la "demi-distance".0 votes
@GrzegorzSzpetkowski On dirait que vous avez trouvé le bug ? Ou y a-t-il une raison derrière le choix d'un type signé ? Sinon, vous devriez poster ceci en tant que réponse à la question et quelqu'un pourrait alors déposer un rapport de bogue.
1 votes
@Lundin : Je n'ai pas trouvé de commentaires sur la raison pour laquelle ils prennent le type signé, donc il peut s'agir d'un bug. Edit : Je pense que 2501 a raison et que c'est dû à
ptrdiff_t
qui est signé.0 votes
Le matériel actuel utilise 48 bits d'espace d'adressage virtuel. Si vous n'avez pas de types d'entiers de 48 bits, vous devrez utiliser un espace d'adressage virtuel de 64 bits.
size_t
.5 votes
Vous remarquerez que rien dans la norme n'implique que le compilateur doive autoriser des objets de n'importe quelle taille jusqu'à
SIZE_MAX
. Cela implique seulement que le compilateur ne doit pas autoriser des objets plus grands queSIZE_MAX
. Cela est vrai même si vous ne créez pas réellement l'objet, puisquesizeof
peut également s'appliquer aux types.0 votes
Concernant le premier paragraphe,
size_t
contient des valeurs entières, pas des types.0 votes
Une version plus "conforme aux normes" : stackoverflow.com/questions/9386979/
0 votes
Je préfère l'explication de @AnT à celle choisie, mais en fin de compte je me demande s'il n'est pas préférable de fermer cette question en double et de fusionner ce contenu dans l'autre question qui est liée. Vous êtes certainement Il est légitime de poser cette question, mais elle ne nécessite qu'une extension mineure de l'autre question. Il semble que ce dont StackOverflows a besoin, c'est d'une réponse canonique sur size_t/ptrdiff_t/intptr_t, et que toutes les autres questions soient closes.