Utilisation de uint8, uint16 etc

actuellement je travaille avec une base de code (C, C++ mixed) ciblée pour une plateforme mips 32 bits. Le processeur est assez moderne [juste pour mentionner que nous avons une bonne quantité de puissance de traitement et la mémoire].

La base de code utilise des types de données comme uint8[1 octet entier non-signé], uint16[2 octet entier non-signé], uint32[4 octet entier non-signé], etc.

je sais comment l'utilisation de ces constructions est utile tout en portant le code à différents plate.

Mes questions sont:

  1. Quel est l'usage ou l'avantage d'utiliser un uint16 lorsqu'un uint32 sera également suffisant (s'il y en a)?

  2. y aura-t-il des économies dans l'utilisation de la mémoire en utilisant des types de données plus courts (en tenant compte de l'alignement des données)?

  3. si c'est pour sauver quelques octets de mémoire, est-ce quelque chose de raisonnable à faire dans le matériel moderne?

18
demandé sur CharlesB 2013-02-25 11:55:37

9 réponses

Quel est l'usage ou l'avantage d'utiliser un uint16 lorsqu'un uint32 sera également suffisant (s'il y en a)?

Si ces uint16s sont des parties de tableaux ou de structures, vous pouvez sauver la mémoire et peut-être être en mesure de gérer des ensembles de données plus grands qu'avec uint32s dans ces mêmes tableaux ou des structures. Cela dépend vraiment de votre code.

les protocoles de données et les formats de fichiers peuvent utiliser uint16s et il peut ne pas être correcte à utiliser uint32s à la place. Cela dépend du format et sémantique (par exemple si vous avez besoin de valeurs pour passer de 65535 à 0, uint16 le fera automatiquement pendant que uint32 ne va pas).

otoh, que, si ces uint16s ne sont que des variables locales ou globales simples, les remplacer par des variables à 32 bits pourrait ne pas faire de différence significative car elles sont susceptibles d'occuper le même espace en raison de l'alignement et elles sont passées en paramètres à 32 bits (sur la pile ou dans les registres) sur les MIPS de toute façon.

y aura-t-il des économies dans utilisation de la mémoire dans l'utilisation de types de données plus courts (compte tenu de l'alignement des données)?

il peut y avoir des économies, surtout quand uint16s sont des parties de plusieurs structures ou éléments de grands tableaux.

si c'est pour sauver quelques octets de mémoire, est-ce quelque chose de raisonnable à faire dans le matériel moderne?

Oui, vous réduisez la bande passante mémoire (ce qui est toujours une bonne chose) et vous réduisez souvent le nombre de trous de cache (caches de données et TLB) lorsque vous opérez sur moins de données.

22
répondu Alexey Frunze 2013-02-25 08:22:46

tout d'Abord si vous avez des types comme uint16 défini, où sont-ils définis? Ils ne sont pas des types standards, donc seront définis dans un en - tête propriétaire-peut-être le vôtre ou peut être fourni par une bibliothèque tierce partie; dans ce cas, vous devez vous demander comment le code est portable, et si vous créez une dépendance qui pourrait ne pas avoir de sens dans une autre application.

un autre problème est que de nombreuses bibliothèques (mal avisées IMO) définissent de tels types avec divers noms tels que UINT16, uint16, U16 UI16 etc. qu'il devient un peu un cauchemar en assurant un accord de type et en évitant des conflits de noms. Si ces noms définis, ils devraient idéalement être placés dans un espace de noms ou un préfixe spécifique à une bibliothèque pour indiquer avec quelle bibliothèque ils ont été définis, par exemple rtos::uint16rtos_uint16.

puisque la bibliothèque standard ISO C99 fournit des types standards spécifiques à la longueur de bits dans stdint.h, vous devriez préférer leur utilisation sur tout défini dans un en-tête propriétaire ou tiers. Ces types ont un _t suffixe, par exemple,uint16_t. En C++, ils peuvent être placés dans le std:: namespace (bien que ce ne soit pas donné puisque l'en-tête a été introduit en C99).

1] Quel est l'usage ou l'avantage d'utiliser un uint16 lorsqu'un uint32 sera également suffisant (s'il y en a)?

mis à part mon conseil précédent de préférer stdint.huint16_t, il y a au moins deux raisons légitimes d'utiliser la longueur des types spécifiques:

  1. pour correspondre à une largeur de Registre spécifique.
  2. pour appliquer une API commune et compatible à travers différentes architectures.

2] y aura-t-il des économies dans l'utilisation de la mémoire en utilisant des types de données plus courts (en tenant compte de l'alignement des données)?

peut-être, mais si la mémoire n'est pas votre problème, ce n'est pas une bonne raison de les utiliser. Peut-être vaut-il la peine d'envisager pour les grands objets de données ou tableaux, mais appliquer à l'échelle mondiale vaut rarement la peine.

3] Si c'est pour sauver quelques octets de mémoire, est-ce quelque chose de raisonnable à faire dans le matériel moderne?

voir [2]. "matériel Moderne " cependant, cela n'implique pas nécessairement des ressources importantes; il y a beaucoup de Cortex-M à bras 32 bits avec seulement quelques Kb DE RAM par exemple. Il s'agit plus de l'espace, du coût et de la consommation d'énergie que de l'âge du design ou de l'architecture.

9
répondu Clifford 2013-02-25 10:03:36

cstdint a des charges de typedefs à des fins différentes.

  • intN_t pour une largeur
  • int_fastN_t pour l'entier le plus rapide, qui a au moins N bits
  • int_leastN_t pour le plus petit entier, qui a au moins N bits
  • leur unsigned équivalents

Vous devez choisir en fonction de vos circonstances. Stocker des milliers dans un std::vector et ne pas faire des charges de calcul? intN_t est probablement votre homme. Besoin rapide calcul sur un petit nombre d'entiers? int_fastN_t est probablement votre mec.

3
répondu Alex Chamberlain 2013-02-25 08:16:30

Ans. 1. Le logiciel a certaines exigences et spécifications qui dit strictement de ne prendre que 8/16-bits d'un paramètre tout en encodant/décodant ou une autre utilisation certaine. Donc, même si u assigne une valeur supérieure à 127 dans un u8, par exemple, cela altère les données automatiquement pour vous.

Ans. 2. Nous ne devons pas oublier que nos compilateurs sont bien au-delà de l'intelligence pour faire l'optimisation, que ce soit la mémoire ou la complexité. Il est donc toujours recommandé d'utiliser une mémoire plus petite lorsque possible.

Ans. 3. Bien sûr, sauver la mémoire a du sens sur H/w Moderne.

2
répondu paper.plane 2013-02-25 08:03:27

en utilisant uint16_t au lieu de uint32_t enregistre la mémoire. Il peut aussi s'agir d'une contrainte matérielle (par exemple, un contrôleur périphérique envoie réellement 16 bits!) Cependant, il ne vaut peut-être pas la peine de l'utiliser, à cause de considérations de cache et d'alignement (vous devez vraiment faire un benchmark).

1
répondu Basile Starynkevitch 2013-02-25 07:58:36

Les réponses à vos questions se résume à un concept clé: Quelle est la taille des données? Si vous utilisez beaucoup de données, alors l'avantage d'utiliser des types de données plus petits est évident. Pensez - y de cette façon: simplement en calculant le premier plus grand connu nouvellement découvert pourrait vous faire manquer de mémoire sur une station de travail typique. Le nombre lui-même prend plus d'un gigaoctet juste pour les stocker. Cela n'inclut pas de travailler jusqu'à calculer le nombre réel. Si vous deviez utiliser un type de données épais au lieu d'un mince, il se peut que vous regardiez deux gigaoctets à la place. Un exemple simpliste, mais bon tout de même.

1
répondu L0j1k 2013-02-25 08:02:38

utilisant des types d'entiers de largeur exacte comme int32_t and friends est utile pour éviter les bogues d'extension de signe entre les plates-formes qui ont des tailles différentes pour int et long. Cela peut se produire lors de l'application de masques de bits ou lors du déplacement de bits, par exemple. Si vous effectuez ces opérations sur un long par exemple, et votre code fonctionne pour un 32-bit