Δημοσιεύτηκε: 09 Σεπ 2011, 14:17
από migf1
Λοιπόν ο παρακάτω κώδικας χρησιμοποιεί ένα struct κι ένα union για να διαχειρίζεται unsigned bytes. Η βασική δομή είναι το union που αποτελείται από το πεδίο value (για την αριθμητική τιμή του byte) και από το πεδίο bits (για τα δυαδικά ψηφία του byte).

To πεδίο value είναι ένας unsigned char, που όπως ξέρουμε ισοδυναμεί με unsigned byte.

Το πεδίο bits είναι μια δομή struct, η οποία αποτελείται από 8 πεδία, ένα για κάθε δυαδικό ψηφίο. Εκείνο το :1 που βλέπετε κολλημένο δίπλα στο καθένα από αυτά τα πεδία είναι ο τρόπος της C για να ορίζουμε πόσα bits θέλουμε να πιάνει κάθε πεδίο μιας δομής... εμείς θέλουμε να πιάνουν 1 bit, για αυτό κι έχουμε σε όλα :1.
Έχουν και ειδική ονομασία τα πεδία αυτά στη C, ονομάζονται bitfields

Άρα λοιπόν, ορίζοντας μια μεταβλητή byte τύπου Byte (union byte), μπορούμε να διαχειριστούμε τα περιεχόμενά της είτε ως:
Κώδικας: Επιλογή όλων
byte.value

είτε ως:
Κώδικας: Επιλογή όλων
byte.bits.bX
όπου Χ b1 έως b8

Αν π.χ. γράψουμε:
Κώδικας: Επιλογή όλων
byte.value = 2;

ενημερώνονται ταυτόχρονα και το πεδίο .value και το .bits.

Ομοίως, αν γράψουμε:
Κώδικας: Επιλογή όλων
byte.bits.b1 = true;
byte.bits.b7 = true;

ενημερώνεται ταυτόχρονα και το πεδίο .value.

Μετά από κάθε ανάθεση τιμής είτε στο .value είτε σε μεμονωμένα .bits.bX μπορείτε να δείτε το αποτέλεσμα καλώντας τη συνάρτηση print_byte().

Έβαλα δυο ακόμα συναρτήσεις, μια byte_resetbits( *byte ) που σβήνει μονομιάς όλα τα bits του byte, και μια byte_setbits( *byte ) που τα ανάβει μονιμιάς όλα μαζί.

ΣΗΜΕΙΩΣΗ:
Την τεχνική με τα unions για την αναπαράσταση δυαδικών ψηφίων χρησιμοποιήστε την μονάχα ΑΝ δεν σας ενδιαφέρει η σειρά των bits ή αν σας ενδιαφέρει αλλά την ξέρετε από πριν, και άρα θα προσαρμόσετε ανάλογα τη σειρά τους μέσα στο struct των bits. Για παράδειγμα, σε μηχανήματα X86 (όπως τα δικά μας) τα δυαδικά ψηφία τυπώνονται με ΑΝΑΠΟΔΗ ΣΕΙΡΑ !!!!!

Με λίγα λόγια, η τεχνική αυτή δεν είναι portable (δεν είναι cross-platform). Αν θέλετε να διαχειριστείτε bits με portable κώδικα, χρησιμοποιήστε τους ειδικού τελεστές (bit operators) για να απομονώνετε τα bits που θέλετε, όπως δείχνω σε αυτό εδώ το πρόγραμμα: viewtopic.php?f=6&t=19815&p=205079#p205079 (εκείνο έχει ακόμα πιο προχωρημένα πράγματα).

Ιδού και ο τωρινός κώδικας:
Κώδικας: Επιλογή όλων

#include <stdio.h>
#include <stdbool.h>

typedef struct bits // structure of 8 bitfields (1 bit per field)
{ // !!!! their order is MACHINE DEPENDENT !!!!
_Bool b1:1;
_Bool b2:1;
_Bool b3:1;
_Bool b4:1;
_Bool b5:1;
_Bool b6:1;
_Bool b7:1;
_Bool b8:1;
} Bits;

typedef union byte { // an unsigned byte represented as union
unsigned char value; // ... the numerical rerpesentation of the byte
Bits bits; // ... the bit representation of the byte
} Byte;

// -------------------------------------------------------------------------------------
// reset all byte bits to 0
//
void byte_resetbits( Byte *byte )
{
byte->bits.b1 = false;
byte->bits.b2 = false;
byte->bits.b3 = false;
byte->bits.b4 = false;
byte->bits.b5 = false;
byte->bits.b6 = false;
byte->bits.b7 = false;
byte->bits.b8 = false;

return;
}
// -------------------------------------------------------------------------------------
// set all byte bits to 1
//
void byte_setbits( Byte *byte )
{
byte->bits.b1 = true;
byte->bits.b2 = true;
byte->bits.b3 = true;
byte->bits.b4 = true;
byte->bits.b5 = true;
byte->bits.b6 = true;
byte->bits.b7 = true;
byte->bits.b8 = true;

return;
}
// -------------------------------------------------------------------------------------
// print all byte bits (the order is machine dependent)
//
void print_bytebits( Byte byte )
{
printf( "%u%u%u%u%u%u%u%u",
byte.bits.b1,
byte.bits.b2,
byte.bits.b3,
byte.bits.b4,
byte.bits.b5,
byte.bits.b6,
byte.bits.b7,
byte.bits.b8
);
return;
}
// -------------------------------------------------------------------------------------
void print_byte( Byte byte )
{
printf("byte value : %u\n", byte.value );

printf("byte bits : " );
print_bytebits( byte );

puts("\n");

return;
}
// -------------------------------------------------------------------------------------
int main( void )
{
Byte byte;

byte.value = 1; // assign decimal value of 1 to byte
print_byte( byte );

byte.value = 2; // assign decimal value of 2 to byte
print_byte( byte );

byte_resetbits( &byte ); // reset all byte bits to 0
print_byte( byte );

byte_setbits( &byte ); // set all byte bits to 1
print_byte( byte );

return 0;
}


Έξοδος:
Κώδικας: Επιλογή όλων

byte value : 1
byte bits : 10000000

byte value : 2
byte bits : 01000000

byte value : 0
byte bits : 00000000

byte value : 255
byte bits : 11111111


Βομβαρδίστε με απορίες ελεύθερα :)

Και μετά θα δούμε πως να αποθηκεύουμε διευθύνσεις δεικτών με χρήση unions (μάλλον είναι πιο εύκολο αυτό από ότι τα bits)