Enum 8 bits, en C

Je dois stocker des instructions, des commandes que je vais recevoir via serial. Les commandes seront longues de 8 bits.

J'ai besoin de préserver la transparence entre le nom de la commande et sa valeur. Afin d'éviter d'avoir à traduire un nombre de 8 bits reçu en série en n'importe quel type.

Je voudrais utiliser des énumérations pour les traiter dans mon code. Seule une énumération correspond à A sur cette plate-forme un entier de 16 bits.

La plate-forme est AVR ATmega169V microcontrôleur, sur le Papillon carte de démonstration. C'est un système 8 bits avec un support limité pour les opérations 16 bits. Ce n'est pas un système rapide et a environ 1KB de RAM. Il n'a pas de luxe comme les e / s de fichiers ou les systèmes d'exploitation.

Donc, des suggestions sur le type que je devrais utiliser pour stocker des commandes 8 bits?
Il doit y avoir quelque chose de mieux qu'un en-tête massif de #defines.

23
demandé sur Lyndon White 2009-11-09 09:38:27

6 réponses

gcc's -fshort-enums pourrait être utile:

Allouer à un type "enum" uniquement comme de nombreux octets dont il a besoin pour le plage déclarée de valeurs possibles. Plus précisément, le type "enum" sera équivalent à le plus petit type entier qui a assez de place.

En fait, Voici une page avec beaucoup d'informations pertinentes. J'espère que vous rencontrerez de nombreux commutateurs GCC que vous n'avez jamais connus. ;)

36
répondu Michael Foukarakis 2010-04-04 20:49:45

Vous essayez de résoudre un problème qui n'existe pas.

Votre question est étiquetée C. Dans le langage C, les types enum dans le contexte de valeur sont entièrement compatibles avec les types intégraux et se comportent comme les autres types intégraux. Lorsqu'ils sont utilisés dans des expressions, ils sont soumis exactement aux mêmes promotions intégrales que les autres types intégraux. Une fois que vous prenez cela en compte, vous devez réaliser que si vous voulez stocker des valeurs décrites par des constantes d'énumération dans un type intégral de 8 bits, tout ce que vous devez do est de choisir un type intégral Générique 8 bits approprié (par exemple int8_t) et de l'utiliser à la place du type enum. Vous ne perdrez absolument rien en stockant vos valeurs constantes enum dans un objet de type int8_t (par opposition à un objet explicitement déclaré avec le type enum).

Le problème que vous décrivez existerait en C++, où les types enum sont séparés beaucoup plus loin des autres types intégraux. En C++, l'utilisation d'un type intégral à la place du type enum dans le but d'économiser de la mémoire est plus difficile (bien que possible). Mais pas en C, où il ne nécessite aucun effort supplémentaire que ce soit.

6
répondu AnT 2010-02-27 08:13:39

Je ne vois pas pourquoi une énumération ne fonctionnerait pas. Les comparaisons et les affectations à partir d'une énumération devraient toutes fonctionner correctement avec l'élargissement par défaut. Veillez simplement à ce que vos valeurs de 8 bits soient signées correctement (je pense que vous voudriez une extension non signée).

Vous obtiendrez des comparaisons 16 bits de cette façon, j'espère que ce ne sera pas un problème de performance (ce ne devrait pas être le cas, surtout si votre processeur est 16 bits comme on dirait).

3
répondu Keith Randall 2009-11-09 06:43:21

Le compilateur C de Microsoft vous permet de faire quelque chose comme ça, mais c'est une extension (c'est standard en C++0x):

enum Foo : unsigned char {
    blah = 0,
    blargh = 1
};

Puisque vous avez marqué GCC, Je ne suis pas tout à fait sûr si la même chose est possible, mais GCC pourrait avoir une extension en mode gnu99 ou quelque chose pour cela. Lui donner un tourbillon.

1
répondu Jed Smith 2009-11-09 06:45:51

Je recommande de rester sur enum dans tous les cas pour les raisons suivantes:

  • Cette solution vous permet de mapper les valeurs de commande directement à ce que votre protocole série attend.
  • Si vous utilisez vraiment l'architecture 16 bits, il n'y a pas si grand nombre d'avantages à passer au type 8 bits. Pensez à des aspects autres que 1 octet de mémoire enregistré.
  • dans certains compilateurs, j'ai utilisé la taille enum réelle utilisée nombre minimal de bits (les énumérations qui pourraient être ajustées en octet utilisé uniquement octet, puis 16 bits puis 32).

D'abord, vous ne devriez pas vous soucier de la largeur de type réel. Seulement si vous avez vraiment besoin d'un moyen de stockage efficace, vous devriez utiliser des drapeaux du compilateur tels que-fshort-enums sur le compilateur GNU, mais je ne les recommande pas sauf si vous en avez vraiment besoin.

En tant que dernière option, vous pouvez définir 'enum' comme données de présentation pour les commandes et utiliser la conversion en octet avec 2 opérations simples pour stocker / restaurer la valeur de la commande dans / depuis la mémoire (et l'encapsuler en un seul endroit). Quoi à ce sujet? Ceux-ci sont très des opérations simples pour que vous puissiez même les intégrer (mais cela vous permet d'utiliser seulement 1 octet pour le stockage et de l'autre côté pour effectuer des opérations en utilisant la plus utilisable enum définie comme vous le souhaitez.

0
répondu Roman Nikitchenko 2009-11-09 07:00:41

Réponse pertinente pour le compilateur ARC (Cité dans le Guide du programmeur C/C++ de DesignWare MetaWare pour ARC; section 11.2.9.2)

Taille des énumérations la taille d'un type d'énumération dépend de l'état de toggle *Long_enums*.

■ si toggle * Long_enums * est désactivé, le type enum correspond au plus petit d'un, deux ou quatre octets, de sorte que toutes les valeurs peuvent être représentées.

■ si toggle * Long_enums * est activé, une énumération correspond à quatre octets (correspondant la convention du compilateur Portable C AT&T).

0
répondu Morinho 2014-03-05 11:57:47