Frage

Ich bin mit HiTech PICC32 auf der PIC32MX Reihe von Mikroprozessoren zu arbeiten, aber ich denke, diese Frage allgemein genug ist für jedermann sachkundig in C. (Dies ist fast gleichbedeutend mit C90, mit sizeof (int) = sizeof (long) = sizeof (float) = 4).

Lassen Sie uns sagen, ich lese ein 4-Byte-Wort von Daten, die eine float darstellt. Ich kann es auf seinen tatsächlichen Float-Wert schnell konvertieren mit:

#define FLOAT_FROM_WORD(WORD_VALUE) (*((float*) &(WORD_VALUE)))

Das funktioniert aber nur für L-Werte. Ich kann zum Beispiel nicht, verwenden Sie diese auf eine Funktion Rückgabewert wie:

FLOAT_FROM_WORD(eeprom_read_word(addr));

Gibt es eine kurze und süße Art und Weise diese Inline zu tun, das heißt, ohne einen Funktionsaufruf oder temporären Variable? Um ehrlich zu sein, gibt es keinen Grund für mich RIESIG einen Funktionsaufruf oder zusätzliche var zu vermeiden, aber es nervt mich. Es muss einen Weg geben mir persönlich fehlt.

Hinzugefügt: Ich wusste nicht, dass WORD war eigentlich eine gemeinsame typedef. Ich habe den Namen des Makro-Arguments um Verwechslungen zu vermeiden geändert.

War es hilfreich?

Lösung

Sie können den Trick, um die andere Art und Weise für die Rückgabewerte führen

float fl;
*(int*)&fl = eeprom_read_word(addr);

oder

#define WORD_TO_FLOAT(f)  (*(int*)&(f))

WORD_TO_FLOAT(fl) = eeprom_read_word(addr);

oder als R Samuel Klatchko schlägt

#define  ASTYPE(type, val) (*(type*)&(val))
ASTYPE(WORD,fl) = eeprom_read_word(addr);

Andere Tipps

Wenn diese GCC waren, könnten Sie dies tun:

#define atob(original, newtype) \
  (((union { typeof(original) i; newtype j })(original)).k)

Wow. Scheußlich. Aber die Nutzung ist schön:

int i = 0xdeadbeef;
float f = atob(i, float);

ich wette, Ihr Compiler weder den typeof Betreiber noch die union Gießen unterstützt, dass GCC der Fall ist, da weder Standardverhalten, aber in der Off-Chance, dass Ihr Compiler union Casting tun können, die Ihre Antwort. Modifizierte nicht zu verwenden typeof:

#define atob(original, origtype newtype) \
  (((union { origtype i; newtype j })(original)).k)

int i = 0xdeadbeef;
float f = atob(i, int, float);

Natürlich ist dies ignoriert die Frage, was passiert, wenn man zwei Arten von unterschiedlicher Größe verwenden, aber näher an „was Sie wollen“, das heißt eine einfachen Makro-Filter, dass die Renditen ein Wert, anstatt einen zusätzlichen Parameter zu nehmen. Die zusätzlichen Parameter dieser Version erfolgt sind nur für Allgemeinheit.

Wenn Ihr Compiler nicht union Gießen unterstützt, die eine saubere, aber nicht tragbaren Trick ist, dann gibt es keine Möglichkeit, diese das zu tun „wie Sie es wollen“, und die anderen Antworten haben es bereits.

Sie können die Adresse eines temporären Wert nehmen, wenn Sie eine konstante Referenz verwenden:

FLOAT_FROM_WORD(w) (*(float*)&(const WORD &)(w))

, aber das wird nicht funktionieren in c: (

(c keine Verweise Recht hat? Funktioniert in Visual C ++)

wie andere gesagt haben, sei es eine inlined Funktion oder eine temporäre in eine definieren, wird der Compiler optimiert werden.

Nicht wirklich eine Antwort, mehr ein Vorschlag. Ihr FLOAT_FROM_WORD Makro wird natürlicher zu bedienen und flexibler, wenn es sich um ein nicht haben; am Ende

#define FLOAT_FROM_WORD(w) (*(float*)&(w))

fl = FLOAT_FROM_WORD(wd);

Es kann in Ihrer genauen Situation nicht möglich sein, aber ein Upgrade auf einen C99-Compiler würde Ihr Problem lösen.

C99 Inline-Funktionen hat, die zwar wie normale Funktionen in Parameter und Rückgabewerte handeln, genau mit keiner der Nachteile von Makros diesem Fall zu einer verbesserten Effizienz erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top