Journal #define CHAR_BIT 8

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
29
18
oct.
2024

Un séisme cataclysmique fait trembler jusqu'aux fondations du web et ébranle tout le monde connu, les réseaux sociaux sont en feu, Stroustrup refuse de répondre au téléphone, tandis que nous attendons impatiemment une déclaration de nos dirigeants éclairés : le über geek JF Bastien vient de publier une proposition de changement du standard C++ décrétant qu'il y aurait exactement 8 bits dans un byte, prouvant au passage que les français étaient une fois de plus précurseurs en généralisant le terme octet.

Alors vous le savez sans doute, une immense majorité des architectures aujourd'hui font effectivement ce choix, et les compilos modernes sont construits sur ce modèle. L'argument de JF Bastien est donc que non seulement il n'existe presque plus de systèmes où ce n'est pas vrai, mais qu'en plus la minorité de développeurs qui pourraient travailler sur ces architectures n'ont aucun besoin d'un compilateur C++ moderne: "The question isn’t whether there are still architectures where bytes aren’t 8-bits (there are!) but whether these care about modern C++… and whether modern C++ cares about them."

Je sens confusément que je devrais avoir une opinion tranchée sur la question, il ne me reste plus qu'à déterminer laquelle.

  • # Mauvaise idée ?

    Posté par  . Évalué à 1 (+2/-1).

    Celui qui a fait cette proposition parle de la situation présente avec une majorité d'architectures qui codent sur 8 bits, mais il ne semble pas regarder vers le futur.

    Dans le futur, on aura peut-être besoin d'octets plus gros, par exemple 10 bits. Les nouveaux écrans codent déjà les couleurs sur 10 bits au lieu de 8.

    Donc figer la taille d'un octet à 8 bits, c'est peut-être une mauvaise idée.

  • # Question probablement bête

    Posté par  (site web personnel) . Évalué à 2 (+1/-1).

    Quelqu'un peut expliquer le rapport entre char et octet ?

    Adhérer à l'April, ça vous tente ?

    • [^] # Re: Question probablement bête

      Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

      Actuellement il n'y en a pas vraiment. En C et en C++, on définit que sizeof(char) vaut 1. Quand on incrémente un pointeur sur un char, il s'incrémente donc de 1. Il est impossible d'avoir un type de données plus petit (sauf les booléens et les bitfields), et les types plus gros sont des multiples de la taille d'un char. Mais, on peut implémenter le C et le C++ avec n'importe quel nombre de bits dans un char.

      Il existe quelques architectures incapables d'adresser la mémoire plus finement que 16 ou même 32 octets. En particulier: des machines dont le jeu d'instruction n'est pas un lointain descendant du PDP-11; et certaines familles de DSP conçus par exemple pour le traitement du son en 16 bit.

      Pour aaoir récement implémenté un compilateur C sur une telle architecture, je confirme qu'il a été relativement difficile de trouver une chaîne d'outils capable de prendre cela en compte (mais j'ai finalement convaincu les développeurs de vbgc et de vasm de se pencher sur le problème). Je regrette de ne pas pouvoir faire de C++ sur ce système pour l'instant, c'est un langage intéressant pour réaliser de nombreuses optimisations à la compilation qui me seraient bien utiles,

      • [^] # Re: Question probablement bête

        Posté par  (site web personnel) . Évalué à 2 (+0/-0).

        Je posais la question car l'auteur de la proposition a l'air de considérer évident et implicite (dès le titre) que char et byte c'est la même chose, alors que ça pourrait me semble à étayer dans un doc de normalisation. :)

        Adhérer à l'April, ça vous tente ?

      • [^] # Re: Question probablement bête

        Posté par  . Évalué à 4 (+4/-1).

        Alors, je serais vous, je vérifierais systématiquement que sizeof(char) == 1.

        Retour quasi 10 ans en arrière. R&D pour le développement d'une enceinte Bluetooth.
        Est-ce qu'on pourrait faire tout avec la puce à la mode à l'époque, à savoir, la CSR 8670 ?

        NB: CSR est une boîte anglaise spécialisée dans ce genre de puce. Était, puisque rachetée par Qualcomm en 2015.

        Globalement : non, pas possible. Mais il a fallu passer quelques mois pour prendre la mesure de la perfidie des grands bretons. Sur le papier, elle est géniale cette puce : en plus du Bluetooth évidemment, un MCU accompagné de son DSP, trop cool.

        En pratique … Énormément de pipo des commerciaux et technico-commerciaux …

        Outre les limitations de ressources hallucinantes, les limites très mal documentées de l'unique fonction pour communiquer sur le bus I2C, après quelques bizarreries, j'ai fini par afficher la valeur de sizeof(uin8_t).

        Réponse : 2.

        Oui, 2.

        Le support a été incapable de m'expliquer pourquoi.
        J'ai trouvé la réponse seul, par hasard, sur le forum concernant une autre de leurs puces.
        Réponse : c'est légal, c'est autorisé par la norme C, un octet ne fait pas forcément 8 bits.

        OK. Pour l'I2C en particulier, c'était déjà la merˆWpanade, alors transférer de la data stockée dans un tableau dont on ignore comment seront traités les "trous" …
        Et quid de l'arithmétique des pointeurs ? Il avance de 1 ou de 2 quand je fais ++ ? Pour coller au sizeof, ce serait 2. Pour revenir à cette fonction de transfert sur l'I2C : est-ce que les "trous" sont transférés ? Est-ce que je dois plutôt gérer un tableau de uint16_t ? Quid de l'endianess ?…

        Cette épée de Damoclès en permanance sur ce qui se passe au plus bas niveau … Stressant …
        Je vous raconte pas les nœuds au cerveau et le doute permanent sur le comportement du chip.

        Conclusion : le gars qui customise un compilo pour en arriver là, c'est le diable en personne !

        À moins que quelqu'un connaisse un cas de figure où c'est justifié ? Est-ce que c'est plus répendu que je ne le pense ?

        Non, récupérer apacher une vieille architecture moisie des années 80s n'est pas une excuse acceptable !

        • [^] # Re: Question probablement bête

          Posté par  (site web personnel) . Évalué à 9 (+7/-0). Dernière modification le 19 octobre 2024 à 13:54.

          Réponse : c'est légal, c'est autorisé par la norme C, un octet ne fait pas forcément 8 bits.

          Alors une chose de sûr, un octet fait forcément 8 bits, c'est sa définition, dans un dico et tout et tout (octet, et du latin), j'imagine donc que tu voulais parler d'une byte ou multiplet

          Ensuite, la j'aimerai l'argument, qu'on me corrige si je me trompe mais il me semble que le standard dit que :
          uint8_t fait exactement 8 bit
          sizeof(char) fait forcément 1
          la taille minimum de char est 8
          Partant de ces postulats, mathématiquement sizeof(uint8_t) ne peut pas être autre chose que 1 (aucune taille de char, la seule chose variable, peut faire une autre valeur sans manquer de respecter une des règles, genre il faudrait que la taille d'un char soit 4 qui n'est pas valide).

          Conclusion : le gars qui customise un compilo pour en arriver là, c'est le diable en personne !

          Clairement, et on peut supposer que c'est un gros bug mais qu'ils ne veulent pas corriger à cause de conséquences chiantes à gérer.

          • [^] # Re: Question probablement bête

            Posté par  . Évalué à 3 (+2/-0).

            1) la définition du dico n'est pas celle de la norme je pense
            2) je suis d'accord, on ne sait plus où on habite si sizeof(uint8_t) != 1, ...16... != 2, etc
            3) je "garantie sur facture" que j'ai vu et contrôlé de mes yeux vu un sizeof(uint8_t) --> 2; et que d'après les références pointées à l'époque sur le forum CSR, la norme l'autorise. Ça n'était pas un bug.

            Mais bon, je parle de norme sans la connaître, étant plus du genre empirique. Si quelqu'un ici l'a lue et sait retrouver la référence précise que j'ai pu lire à l'époque, merci d'avance.

            Ceci dit, ma mémoire peut me jouer des tours, plus souvent que je ne le pense, mais j'ai retrouvé un bout de conversation que j'ai eu avec les potes, tellement j'étais surleculté par cette mauvaise surprise. J'avais les idées fraiches à l'époque, et donc, je venais tout juste d'expérimenter ça :

            En particulier, j'ai une fonction de transfert de data sur bus I2C. Elle prend effectivement du uint8 * en input, en précisant bien que chaque uint8 fait un word, et donc 16 bits !
            Ça veut dire aussi que mon buffer doit faire le double de la taille de data à envoyer !

            Magnifique ! En embarqué, avec des ressources limitées !

            Par ailleurs, tout ça permet à un unsigned char d'avoir une valeur supérieure à 255. Va me falloir du temps pour m'y faire à celle-là !

            • [^] # Re: Question probablement bête

              Posté par  (site web personnel) . Évalué à 4 (+2/-0).

              1) la définition du dico n'est pas celle de la norme je pense

              La il va falloir me confirmer que la norme utilise le mot "octet", vu le sujet du journal j'ai un gros doute, je suis prêt à tenir un pari avec enjeux avec toi sur byte.

              Mais bon, je parle de norme sans la connaître

              Voila :)

              Par ailleurs, tout ça permet à un unsigned char d'avoir une valeur supérieure à 255. Va me falloir du temps pour m'y faire à celle-là !

              Le norme est claire : char n'est pas uint8_t, et char a minimum 8 bits, ça implique pas forcément 8, et donc oui un unsigned char peut avoir une valeur supérieure à 255, rien d'anormal, juste pas courant de nos jours sans que la spec ne l'interdise, du moment pour le moins (d'où le sujet du journal).

              • [^] # Re: Question probablement bête

                Posté par  (site web personnel, Mastodon) . Évalué à 5 (+3/-0).

                Moi ce que j'ai retenu de la norme c'est que int8_t peut ne pas être défini si jamais ton architecture ne permet pas d'adresser les choses par mots de 8 bits.

                Par contre il peut y avoir des types int_least8_t (au moins 8 bits) et int_fast8_t (au moins 8 bits, et plus large si ça lui permet d'être plus rapide).

                Je crois que ça n'empêche ps d'avoir sizeof(int8_t)=2: ça voudrait dire que le compilateur génère automatiquement des opérations qui masquent 8 des 16 bits pour que le code écrit aie effectivement un type qui se comporte comme s'il n'avait que 8 bits, mais qui prend plus de place, avec des bits qui se retrouve inutilisés.

                • [^] # Re: Question probablement bête

                  Posté par  (site web personnel) . Évalué à 1 (+0/-1). Dernière modification le 20 octobre 2024 à 21:46.

                  ça voudrait dire que le compilateur génère automatiquement des opérations qui masquent 8 des 16 bits

                  ah… ça y est, j'ai ma lumière éclairée.
                  Effectivement, rien ne semble interdire en pratique de stocker plus gros tant que 255+1 donne 0… J'avais mis une contrainte qui n'est sans dont pas dans la spec, celle que ce soit une seule opération, "uint8_t fait exactement 8 bit" est peut-être "uint8_t doit se comporter comme si il fait exactement 8 bit" et dans ce cas la ma conclusion n'est plus bonne.

                  Mais du coup :

                  Moi ce que j'ai retenu de la norme c'est que int8_t peut ne pas être défini si jamais ton architecture ne permet pas d'adresser les choses par mots de 8 bits.

                  semble faux puisque dans ce que tu dis à peut être 16 bits, du moment où le résultat est comme 8 bits.

                  • [^] # Re: Question probablement bête

                    Posté par  (site web personnel, Mastodon) . Évalué à 5 (+3/-0).

                    Il n'y a pas de contradiction: la norme autorise à ne pas définir le type int8_t si on nwa pas envie de l'implémenter (par exemple parce que c'est compliqué à faire). Elle autorise aussi à l'implémenter de façon compliquée et lente.

                    Pas mal de choses en C sont ainsi laisséesau choix de l'implémentation, comme par exemple le nombre de bits dans un char. Sur certaines choses, le choix était laissé avant et ce n'est plus le cas: l'utilisation d'autre chose que le complément à 2 pour les nombres négatif, le comportement de l'opérateur modulo avec un opérande négatif, par exmple.

  • # J'hésite

    Posté par  (site web personnel) . Évalué à 9 (+8/-1).

    Aucun doute qu'en dehors de quelques architectures exotiques on aura 8 bits dans un char. Néanmoins, comme pour trop de nouveautés du C++ de ces dix dernières années, je me demande quel problème ce papier essaye de résoudre.

    The complexity of supporting non-8-bit byte architectures sprinkles small but unnecessary burden in quite a few parts of language and library;

    Sans doute. Des exemples peut-être ? Histoire qu'on puisse juger de cette charge ajoutée.

    Compilers and toolchains are required to support edge cases that do not reflect modern usage;

    Oui ce n'est pas moderne, mais faut-il jeter tout ce qui n'est pas moderne ? Le C++ n'est pas un langage moderne de toute façon.

    New programmers are easily confused and find C++'s exotic tastes obtuse;

    Et ? Les nouveaux programmeurs on en effet tout à apprendre du langage et de son histoire.

    Some seasoned programmers joyfully spend time supporting non-existant platforms "for portability" if they are unwise;

    Un peu de temps perdu pour quelques programmeurs. Okay, pas vraiment un problème mais pourquoi pas.

    Our language looks silly, solving problems that nobody has.

    Avec un lien vers un tweet. Bon, un type sur Internet trouve le langage idiot. Qui ça intéresse ?

    À mon humble avis le comité passe beaucoup trop de temps à essayer de se convaincre que ce langage n'est pas dépassé. On peut mettre autant de qualificatifs modern ou contemporary à côté de son nom, le C++ est factuellement un langage de vieux. La plupart des programmes écrits en C++ sont de vieux trucs, et c'est normal vu son âge. Si vous voulez un langage moderne et performant il y a d'autres candidats plus pertinents.

    L'argument de l'attention aux jeunes programmeur est fallacieux. Chaque couche de modernisation est une chose supplémentaire à comprendre pour les devs C++.

    • [^] # Re: J'hésite

      Posté par  . Évalué à 4 (+6/-2).

      En quoi le C++ serait dépassé ?

      C'est un langage vieux, et alors ?

      Quel est l'intérêt d'utiliser un langage apparu récemment ?

      Et quels sont les langages performants plus pertinents que le C++ ?

      • [^] # Re: J'hésite

        Posté par  (site web personnel, Mastodon) . Évalué à 3 (+4/-2).

        En quoi le C++ serait dépassé ?

        Il est de plus en plus lourd et complexe. Il est pas sécurisé (du moins pas au top). Ses spécification sont fermées…

        C'est un langage vieux, et alors ?

        Il n'est pas ce qui se fait de mieux.

        Quel est l'intérêt d'utiliser un langage apparu récemment ?

        Plus de sécurité, plus de performances, plus de productivité…

        Et quels sont les langages performants plus pertinents que le C++ ?

        Le Rust de toutes évidence.

        PS: Tu troll un peu alors désolé de troller un peu aussi… Mais mon avis est quand même que Rust est supérieur à C++ sur à peu près tout les points. Reste un point pour C/C++ les bases de codes sont énormes, on doit les maintenir, on doit faire évoluer le C/C++, mais clairement c'est un boulet à trainer (Et c'est normal).

        Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.

      • [^] # Re: J'hésite

        Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

        Il y a plein de décisions discutables mais qui ne changeront pas à cause de la rétrocompatibilité. Pourquoi on a NULL et nullptr? Pourquoi on doit spécifer explicitement const partout alors que ce serait tellement moins piégeux de faire l'inverse et de spécifier les choses qui ne sont pas const? (Le compilateur peut faire un message d'erreur si on essaie de modifier un const, mais pas si on ne modifie pas une variable qui n'est pas const). Pourquoi c'est autorisé d'oublier d'initialiser les membres dans le constructeur d'une classe? Pourquoi on peut stocker des pointeurs mais pas des références dans les conteneurs de la librairie standard? Et ainsi de suite.

  • # Fortran

    Posté par  (site web personnel) . Évalué à 8 (+6/-0).

    Sur les 681 pages de la norme Fortran 2023, le mot byte n'apparaît que dans la section consacrée à l'interopérabilité avec le C. Le mot octet apparaît deux fois.

    Le FORTRAN est né avant que le byte se stabilise sur 8 bits, d'où cette prudence qui peut bien sûr être parfois gênante quand on vit dans les systèmes actuels. Le module intrinsèque iso_fortran_env, introduit avec Fortran 2008, définit néanmoins un KIND INT8 pour les INTEGER.

    • [^] # Re: Fortran

      Posté par  . Évalué à 2 (+0/-0).

      Perso, j'aurai aimé que les anglo-saxons arrêtent d'utiliser bits et Bytes dans leurs unités de mesure, c'est pénible, je ne suis jamais sûr s'il faut une minuscule ou une majuscule.

      Perso, je préfère de loin le terme d'octet, bien plus précis. Je doute de toute façon que tant de programmes que ça fonctionneraient de manière non-bugguée sur des systèmes basés sur des mots trop courts, disons, 4 bits?
      Notamment parce que ça impacterais probablement également la taille de int, short ou long donc la plupart des calculs deviendraient buggués par nature puisqu'ils auraient une tendance a dépasser leurs limites (basses et hautes) et donc a boucler. Et C comme C++ sont très mauvais pour détecter les over/under-flow a ma connaissance.

      • [^] # Re: Fortran

        Posté par  (site web personnel) . Évalué à 3 (+1/-0). Dernière modification le 21 octobre 2024 à 18:51.

        A ma connaissance, il n'y pas de majuscule à bits ou bytes, ce sont des mots comme les autres. Mais effectivement pour les unités de mesure, on écrire Kb pour les kilobits et KB pour les kilobytes. Bref, un petit b pour la petite unité et un gros B pour la grosse…

        Par défaut les langages compilés comme C ou Fortran, ne vérifie pas les overflows des entiers : on fait le tour du compteur kilométrique et on revient de l'autre côté… Mais on peut utiliser une option du compilateur pour rajouter des tests si on veut.

        La norme C définit les tailles minimales que doivent avoir chaque type d'entiers, quelque soit le processeur. Par exemple pour int, c'est [-32767 ; +32767]. Dans la pratique sur les processeurs 64 bits, on a généralement [-2147483648 ; +2147483647] ; c'est indiqué dans /usr/include/limits.h. Donc si on respectait la norme, ça devrait tourner sur d'anciens processeurs, mais on a tendance pour prendre comme acquis les valeurs actuelles.

        • [^] # Re: Fortran

          Posté par  (site web personnel) . Évalué à 4 (+2/-0).

          écrire Kb pour les kilobits et KB pour les kilobytes

          Le grand k c'est pour des grand kilos à 1024 ?

          Adhérer à l'April, ça vous tente ?

          • [^] # Re: Fortran

            Posté par  . Évalué à 2 (+1/-0).

            non, les grands kilos à 1024 sont notés Kibi, par exemple kib, Mio, Gio (par exemple dans l'utilitaire de partionnement GParted)

            ls --help | grep 1024

            Les vrais naviguent en -42

          • [^] # Re: Fortran

            Posté par  (site web personnel) . Évalué à 4 (+2/-0). Dernière modification le 21 octobre 2024 à 20:40.

            Bonne question, oui dans https://en.wikipedia.org/wiki/Kilobyte ils disent :

            The binary meaning of the kilobyte for 1024 bytes typically uses the symbol KB, with an uppercase letter K. The B is sometimes omitted in informal use. For example, a processor with 65,536 bytes of cache memory might be said to have "64 K" of cache.

            1000 kB kilobyte

            1024 KiB kibibyte KB kilobyte

            Je ne parle plus en francs depuis longtemps, mais c'est vrai que j'ai du mal à penser qu'un kilo-octet ça en fait 1000 et non pas 1024… :-)
            C'est certes logique, mais à l'époque des 8 bits, on ne faisait pas la distinction. Avec les puissances de deux, ça donnait l'air intelligent :-)

            Bref, j'aurais effectivement dû écrire kB.

        • [^] # Re: Fortran

          Posté par  . Évalué à 4 (+3/-0).

          Par défaut les langages compilés comme C ou Fortran, ne vérifie pas les overflows des entiers : on fait le tour du compteur kilométrique et on revient de l'autre côté…

          Après vérification du C11 parce que j'avais un doute, en cas d'overflow le comportement est non défini pour les entiers signés

          EXAMPLE An example of undefined behavior is the behavior on integer overflow.

          Mais défini pour les entiers non signés

          A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

        • [^] # Re: Fortran

          Posté par  . Évalué à 2 (+0/-0).

          Bref, un petit b pour la petite unité et un gros B pour la grosse…

          Ah merci pour le moyen mnémotechnique!

          Par défaut les langages compilés comme C ou Fortran, ne vérifie pas les overflows des entiers : on fait le tour du compteur kilométrique et on revient de l'autre côté…

          Ce qui est assez amusant quand des gens qualifient le C d'assembleur portable… on peut même pas vérifier le carry flag… et j'imagine mal une puce ne pas avoir ce type d'info quelque part, bien que je sois ignare en la question (le carry flag est utilisé aussi pour des tests plus classiques de mémoire).
          Mais bon, c'est hors sujet.

  • # UTF-7

    Posté par  (site web personnel) . Évalué à 1 (+1/-1).

    En voici 127 + 1, et c'est déjà trop. Avec un PRINT en basic, et un peu d'ambition, tu pouvais coder le prochain Tomb Raider.

    C64 chars

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.