2
votes

Est-ce que C99 exige qu'un type `int64_t` soit toujours disponible?

La norme C99 exige-t-elle qu'un compilateur conforme ait un int64_t 64 bits défini (et utilisable)? Ou est-ce facultatif et est-il simplement défini par tous les compilateurs populaires? Je pose évidemment des questions spécifiquement sur les plates-formes sur lesquelles le processeur ne peut pas traiter directement les valeurs 64 bits, mais la question est plus générale

Je ne peux pas vraiment comprendre cela sur la page Wikipedia sur les types de données C , ni de cette réponse à une question connexe.


9 commentaires

Je ne suis pas sûr de C99, mais int64_t est définitivement facultatif en C11, sauf quand ce n'est pas le cas. Voir la section 7.20.1.1 de la spécification C11 pour plus de détails.


@ user3386109: Puis-je vous déranger pour un lien? De plus, votre formulation est plutôt cryptique.


Désolé, je n'ai pas de lien. Mais le projet de spécification C11 est disponible gratuitement en ligne et peut être trouvé en recherchant N1570


Lien vers le brouillon C11 . Les types sont facultatifs mais doivent être fournis si l'architecture de la machine a un type approprié, et doivent être fournis si un type entier a les mêmes caractéristiques.


Quoi qu'il en soit, la réponse est «non». Vous ne pouvez pas compter sur les types existants.


Copie possible de Comprendre les types d'entiers à largeur fixe


Existe-t-il des plates-formes sur lesquelles des types de largeur fixe (intXX_t) sont manquants? , L'int8_t de stdint peut-il exister sur une architecture qui n'a pas d'octets 8 bits? , Comprendre les types d'entiers à largeur fixe , Comment vérifier si uint8_t existe en tant que type au lieu d'un caractère non signé? , Les types d'entiers à largeur fixe sont-ils garantis comme des typedefs pour les types intégrés standard?


@phuclv: Tout cela n'est tout simplement pas ce que j'ai demandé.


définitivement oui. Ils disent tous que les entiers de largeur fixe ne sont pas nécessaires sur les systèmes qui ne peuvent pas les prendre en charge. Seule la variante la moins est requise


4 Réponses :


1
votes

Non, C99 n'impose pas de type int64_t .

(Merci @ user3386109, @Clifford)

Un type int64_t n'est pas obligatoire pour être disponible. Citant le projet de document standard C99 N1256 :

7.18.11.1 Types d'entiers de largeur exacte

  1. Le nom typedef int N _t désigne un type entier signé etc. etc. ...
  2. Ces types sont facultatifs. Cependant, si une implémentation fournit des types entiers avec des largeurs de ... 64 bits ... qui ont un complément à deux représentation ... il définira le nom du typedef correspondant.

Mais voyez les réponses de @chux et @ JohnBollinger sur long long ayant 64 bits.


2 commentaires

Utiliser le mot «probablement» ne semble pas être une réponse définitive.


Yuu aurait pu aussi facilement faire référence au projet de C99 et être définitif. open-std.org/jtc1/sc22/wg14/ www / docs / n1256.pdf



2
votes

La norme C99 exige-t-elle qu'un compilateur conforme ait un int64_t 64 bits défini (et utilisable)?

Non, mais C99 nécessite long long qui est au moins 64 bits.

De plus, int64_t est très couramment disponible. Il est très peu probable que vous rencontriez un C99 conforme sans int64_t car il est requis sur presque toutes les plates-formes.

C11dr 7.20.1.1 Types d'entiers de largeur exacte
( int64_t ) .... si une implémentation fournit des types entiers avec largeurs de 8, 16, 32 ou 64 bits, pas de bits de remplissage, et (pour les types signés) qui ont une représentation complémentaire à deux, il définira les noms de typedef correspondants.

La largeur en bits du processeur n'est pas un facteur dans cette fonctionnalité - long long doit exister. Si ce long long (ou n'importe quel type standard est le complément de 64 bits 2), alors int64_t doit exister également. La largeur de bits d'un processeur affecte les performances .


@ Le commentaire R .. souligne qu'un long long qui prend 64 bits de mémoire pour encoder, ne peut, par spécification, prendre en charge que la plage de [-0x7fff-ffff-ffff-ffff .. . + 0x7fff-ffff-ffff-ffff], un timide de la plage int64_t de [-0x8000-0000-0000-0000 ... + 0x7fff-ffff-ffff-ffff]. De telles plates-formes de nos jours sont extrêmement rares, si elles existent.


16 commentaires

C ne nécessite pas que long long soit 64 bits. LLONG_MIN est autorisé à être -0x7fffffffffffffff , ce qui en fait presque 100 zeptobits en moins de 64 bits si l'implémentation fait un si mauvais choix (et, pour des raisons pratiques, 63- bit).


@R .. D'accord "C ne nécessite pas que long long soit 64 bits.", C'est pourquoi la réponse a " long long qui est au moins 64 bits. ". Cela pourrait être plus large. Il pourrait avoir une plage aussi étroite que [-0x7fff-ffff-ffff-ffff ... + 0x7fff-ffff-ffff-ffff]


Il ne nécessite même pas qu'il soit "au moins 64 bits". il doit être au moins 63,999999999999999999921 ... bits. Désolé, mon premier commentaire était mal formulé et manquait la phrase "au moins", mais le fait était que le "au moins" est faux en raison des dispositions en arrière pour permettre les implémentations de complément à un, signe / magnitude et "complément à deux déficient".


@R .. Puisqu'il n'y a pas de bits fractionnaires, c'est la même chose que "au moins 64 bits".


@Barmar: Non, vous devez arrondir vers le bas si vous ne voulez compter que des bits entiers, auquel cas il s'agit en fait de 63 bits (c'est-à-dire que le plus grand intervalle de puissance de deux entièrement représentable dans la plage est de 2 ^ 63 de longueur, pas 2 ^ 64). Une façon de penser à cela est qu'un bit est potentiellement «pas entièrement utilisable».


@R .. Les types signés sont limités au complément à deux commun. Le codage optionnel rare signe et magnitude et complément de uns nécessite également un codage 64 bits minimal. Bien sûr, nous divisons les cheveux / morceaux. ;-)


Notez que la prochaine version de la norme C résoudra ce problème, rendant obligatoire le complément à deux plages complètes pour tous les types d'entiers. Nous devons remercier JF Bastien de SO pour cela! :-)


@R .. Si vous avez besoin d'au moins 63,9999 ... bits et que vous arrondissez à la baisse, vous aurez moins de ce nombre de bits et ne pourrez pas encoder la plage complète.


@R .. Des nouvelles intéressantes sur la prochaine version du C. Vous avez une année prévue?


Je pense que ce sera plus axé sur des questions très importantes comme les trigraphes et ainsi de suite. Toute tentative de modernisation sera opposée par IBM (comme toujours) car ils ont créé il y a 60 ans des architectures étranges et ils veulent que le standard C y soit implémentable


@Barmar: Le fait est que vous ne pouvez pas représenter une plage 64 bits complète sur une telle implémentation, donc si vous voulez traiter long long comme ayant une plage de puissance de deux, vous devez le traiter comme étant seulement 63 bits. Bien sûr, vous pouvez le traiter comme ayant la plage complète de presque 64 bits, mais ce n'est pas une plage de 64 bits et il est incorrect de la décrire comme telle.


@chux: Je pense avoir vu une estimation quelque part mais je ne me souviens pas où. J'ai été en contact avec jfbastien de temps en temps via Twitter et d'autres canaux concernant la proposition et son acceptation, cependant.


@R .. Mon point est de savoir combien de bits vous avez besoin pour représenter la plage requise. Une représentation signe / magnitude ne peut pas représenter la même plage que le complément à deux de 64 bits, mais elle a toujours besoin de 64 bits pour représenter cette plage (63 bits de magnitude, 1 bit de signe).


@Barmar: Généralement, lorsque vous utilisez un type, vous vous souciez de la plage de valeurs qu'il peut représenter, pas (ou du moins plus que) de la quantité de stockage dont il a besoin. Si vous parlez de stockage, vous comptez également les bits de remplissage.


@R .. Bien sûr. Mais vous étiez celui qui a dit "il faut que ce soit au moins 63,999999999999999999921 ... bits", ce qui semble parler de la quantité de stockage.


@Barmar: Il s'agit plutôt d'un espace de valeurs possibles. Les bits fractionnaires ont un sens quand on parle d'entropie / de possibilités.



1
votes

Il existe trois ensembles de types d'entiers :

  • intN_t - comme int64_t et leurs équivalents non signés; ces types exacts peuvent ne pas être disponibles.
  • int_leastN_t - comme int_least64_t ; les types int_least8_t , int_least16_t , int_least32_t et int_least64_t et leurs équivalents non signés sont obligatoires - les autres types sont facultatifs.
  • int_fastN_t - comme int_fast64_t ; les types int_fast8_t , int_fast16_t , int_fast32_t et int_fast64_t sont obligatoires (ils sont le type le plus rapide avec au moins le largeur).

La norme requiert également la prise en charge de long long , et la plage minimale acceptable pour long long nécessite au moins 64 bits (voir §5.2.4.1 Tailles des types d'entiers ). Par conséquent, la norme peut légitimement exiger la prise en charge des types «le moins» et «rapide» à 64 bits ou plus - elle l'exige également pour prendre en charge long long .

Il y avait des ordinateurs avec des mots de 36 bits et d'autres avec des mots de 60 bits. Les deux auraient du mal à fournir (essentiellement, "ne pourraient pas fournir") les types de largeur exacts, mais peuvent facilement fournir un support pour les types "moins" et "rapide".

La norme n'impose pas les 'types de largeur exacte' - voir §7.20.1.1 Types d'entiers de largeur exacte ¶3 :

Ces types sont facultatifs. Cependant, si une implémentation fournit des types entiers avec des largeurs de 8, 16, 32 ou 64 bits, sans bits de remplissage, et (pour les types signés) qui ont une représentation en complément à deux, elle doit définir les noms de typedef correspondants.


5 commentaires

Il y avait des ordinateurs avec des mots de 36 bits et d'autres avec des mots de 60 bits. Le nouveau standard devrait oublier les ordinateurs vieux de 40 à 50 ans. Et oui, il n'y aura pas de compilateurs C21 conformes pour eux. Certains fanatiques standard auraient une crise cardiaque - il n'y aura aucun moyen d'écrire du code portable pour les machines à mémoire de ferrite. Fin du monde. La vie sera insensée.


Ce qui était à peine pertinent il y a vingt ans ne l'est plus aujourd'hui. En 1999, au moins quelques machines de ce type fonctionnaient encore en dehors des musées informatiques. Ces jours-ci, pas tellement.


En outre, il existe des machines de classe DSP avec CHAR_BIT de 16. Ils ont des problèmes avec int8_t , mais pas avec les autres types.


Notez que si int_least64_t est obligatoire pour exister, il n'a pas besoin d'avoir une plage au moins aussi grande que int64_t s'il existait. int_least64_t ne peut descendre que jusqu'à -2 ^ 63 + 1 plutôt que jusqu'à -2 ^ 63. Cela sera corrigé dans la prochaine édition de la norme C. Voir 7.20.2.2 Limites des types d'entiers de largeur minimale .


@JonathanLeffler personne n'écrit de code portable pour eux. Si quelqu'un essaie d'utiliser uint8_t sur eux, devrait trouver un travail plus facile



5
votes

La norme C99 exige-t-elle qu'un compilateur conforme ait un format 64 bits int64_t défini (et utilisable)? Ou est-ce facultatif, et arrive juste à être défini par tous les compilateurs populaires?

Le type est facultatif, dans un sens, et conditionnellement requis dans un sens différent. Plus précisément, C99 dit ,

Le nom typedef intN_t désigne un type entier signé de largeur N , pas de bits de remplissage et une représentation complémentaire à deux. [...]

Ces types sont facultatifs. Cependant, si une implémentation fournit types entiers avec des largeurs de 8, 16, 32 ou 64 bits, sans bits de remplissage, et (pour les types signés) qui ont un complément à deux représentation, il définira les noms de typedef correspondants.

Ainsi, int64_t est facultatif dans le sens où une implémentation conforme n'est pas obligée de fournir un type qui correspond exactement aux caractéristiques d'un int64_t , et si ce n'est pas le cas ' t, alors il n'a pas besoin (en effet, ne doit pas, selon une autre section) fournir le type int64_t .

C99 spécifie qu'il existe un type long long int dont la plage minimale requise nécessite une représentation d'au moins 64 bits de large. Maintenant, il est possible que dans certaines implémentations, il n'y ait pas de type entier signé exactement de 64 bits de large (par exemple, peut-être que int est 24 bits, long 48 et long long 96), et il est possible qu'il existe un type entier de 64 bits de valeur, mais il contient des bits de remplissage ou n'est pas représenté dans le complément à deux. De telles implémentations pourraient être totalement conformes sans toutefois définir un int64_t . Dans la pratique, cependant, aucune implémentation de ce type n'est couramment utilisée aujourd'hui.


2 commentaires

Alors, pouvez-vous avoir un compilateur conforme à C99 qui ne fournit pas int64_t ? Je veux dire, est-ce que long long peut avoir une taille non-power-of-2, ou 128 bits, et int64_t être manquant?


Oui, @einpoklum, en principe vous le pouvez. Comme je l'ai dit, "une implémentation conforme n'est pas obligée de fournir un type qui correspond exactement aux caractéristiques d'un int64_t, et si ce n'est pas le cas, alors il ne doit pas (en fait, ne doit pas [...]) fournir le type int64_t ". Cependant, en pratique, je n'ai connaissance d'aucune implémentation C99 ou C11 conforme existante qui ne parvient pas à fournir int64_t .