Ich muss Union erstellen, die mir erlauben würde, jedes einzelne Bit von einem bestimmten Byte zu bekommen (und anzuzeigen). Macht das überhaupt Sinn? Ich denke, dass ich weiß, wie man das mit bitweisen Operatoren macht, aber keine Ahnung, wie man Unionen für den gleichen Effekt verwendet.C Union - Anzeige aller 8 Bits eines Bytes
Antwort
Es wird empfohlen, bitweise Operationen zu verwenden. Sie kombinieren Vereinigung und Bit-Felder-Bits zu extrahieren, aber beachten Sie, dies ist endianness abhängig, weshalb dies nicht empfohlen, eine Probe hier für das Lernen aber:
#include <stdio.h>
#include <string.h>
union Bits {
char b;
struct bits {
#ifdef LITTLE_ENDIAN
unsigned int b0: 1;
unsigned int b1: 1;
unsigned int b2: 1;
unsigned int b3: 1;
unsigned int b4: 1;
unsigned int b5: 1;
unsigned int b6: 1;
unsigned int b7: 1;
#else
// reverse the order of the bit fields.
#endif
} bits;
};
int main(void) {
char a = 'A';
union Bits b;
b.b = a;
printf("0x%x\n", a);
printf("%d%d%d%d%d%d%d%d\n", b.bits.b7, b.bits.b6, b.bits.b5, b.bits.b4, b.bits.b3, b.bits.b2, b.bits.b1, b.bits.b0);
return 0;
}
Dies sollte Ausgang
0x41
01000001
Nein. Sie können nicht angeben, welche Reihenfolge Bit-Felder sein werden. Die Reihenfolge der Bitfelder ist implementierungsdefiniert. Per ** 6.7.2.1 Struktur- und Gewerkschaftsspezifizierer **, Paragraph 11 des [C-Standards] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf): " ... Die Reihenfolge der Zuweisung von Bitfeldern innerhalb einer Einheit (hochrangig zu niedriger Ordnung oder niedriger Ordnung zu hoher Ordnung) ist implementierungsdefiniert. ... " –
Es ist implementationsdefiniert, deshalb Ich sagte, es hängt von Endianness ab und ist nicht portabel, ich habe nie gesagt, dass man die Reihenfolge des Bitfeldes angeben kann. :) – fluter
Es hängt nicht nur von der Endianess ab - verschiedene Compiler können Bitfelder unterschiedlich behandeln. Sie können also nicht wirklich wissen, welches Bit welches ist. Einige von ihnen sogar vermasseln: https://lwn.net/Articles/478657/ –
Sie können eine Union von unit8_t
und struct
verwenden, die 8 Ein-Bit-Bitfelder enthalten. Auch wenn Sie dadurch auf einzelne Bits zugreifen können, werden Sie nicht wissen, welche Bits sie sind! Dies hängt davon ab, wie Ihr Compiler die Bitfelder dem zugrunde liegenden Byte zuordnet, was von der Endianz Ihres Zielrechners abhängen kann.
Siehe this SO Q&A.
** Sie werden nicht wissen, welche Bits sie sind! ** Danke, dass Sie darauf hingewiesen haben. –
Seit C99 haben wir anonyme Strukturen und Gewerkschaften, die Dinge einfacher:
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
union disByte
{
uint8_t byte;
// Assuming little endian
struct {
bool b0: 1;
bool b1: 1;
bool b2: 1;
bool b3: 1;
bool b4: 1;
bool b5: 1;
bool b6: 1;
bool b7: 1;
};
};
int main()
{
union disByte foo;
foo.byte = 42;
printf("%d %d %d %d %d %d %d %d\n", foo.b0, foo.b1, foo.b2, foo.b3, foo.b4, foo.b5, foo.b6, foo.b7);
}
Allerdings ist das Bit Manipulation in der Regel bevorzugt (Ihre Frage „Bit-manipulati getaggt wurde auf").
#define XTH_BIT_OF(NUM, X) (bool)(NUM & (1U << X))
Die Vorteile der Bit-Manipulation sind:
- Sie nicht über endianness Grund zur Sorge.
- Es sieht kürzer und klarer aus.
Sie können ein Bit-Feld und eine Vereinigung verwenden, um dies so zu tun:
#include <stdio.h>
typedef union {
struct {
unsigned int:0;
unsigned int firstBit : 1;
unsigned int secondBit : 1;
unsigned int thirdBit : 1;
unsigned int fourthBit : 1;
unsigned int fifthBit : 1;
unsigned int sixthBit : 1;
unsigned int seventhBit : 1;
unsigned int eigthBit : 1;
};
int raw;
} bitsOfByte;
int main()
{
bitsOfByte dt;
dt.raw = 254;
printf("Bits are %d/%d/%d/%d/%d/%d/%d/%d", dt.firstBit, dt.secondBit, dt.thirdBit, dt.fourthBit, dt.fifthBit, dt.sixthBit, dt.seventhBit, dt.eigthBit);
return 0;
}
Beachten Sie, dass bei dieser Implementierung ist das erste Bit ist das untere Bit
Dies ist spezifisch für C99 –
Haben Sie Bit-Feld bedeuten stattdessen? Gewerkschaften sind nicht dafür. – fluter
Was ist falsch an der Verwendung bitweiser Operatoren? –