Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 13:35

Μισό παιδιά γιατί πλάκωσε δουλειά, τώρα μόλις χαλάρωσε λιγάκι
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 14:17

Λοιπόν ο παρακάτω κώδικας χρησιμοποιεί ένα 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)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 09 Σεπ 2011, 14:56

Εγώ έχω 2 μέχρι τώρα:
1. Το _Bool είναι μεταβλητή μέσα στο stdbool.h;
2. Πώς γίνεται να μετατρέπεται από value σε byte;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 15:06

stamatiou έγραψε:Εγώ έχω 2 μέχρι τώρα:
1. Το _Bool είναι μεταβλητή μέσα στο stdbool.h;

Ναι, κι αυτό έχει προστεθεί στην αναθεώρηση C99... μπορείς να το σβήσεις τελείως, να δηλώσεις τα bitfields ως unsigned int ή ως unsigned char αντί για _Bool και όταν τους αναθέτεις τιμές χειροκίνητα, αντί για true/false να τους βάζεις 1/0.

έγραψε:2. Πώς γίνεται να μετατρέπεται από value σε byte;

Τι εννοείς; Για εξήγησέ μου καλύτερα.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 09 Σεπ 2011, 15:19

migf1 έγραψε:
stamatiou έγραψε:Εγώ έχω 2 μέχρι τώρα:
1. Το _Bool είναι μεταβλητή μέσα στο stdbool.h;

Ναι, κι αυτό έχει προστεθεί στην αναθεώρηση C99... μπορείς να το σβήσεις τελείως, να δηλώσεις τα bitfields ως unsigned int ή ως unsigned char αντί για _Bool και όταν τους αναθέτεις τιμές χειροκίνητα, αντί για true/false να τους βάζεις 1/0.

έγραψε:2. Πώς γίνεται να μετατρέπεται από value σε byte;

Τι εννοείς; Για εξήγησέ μου καλύτερα.

Εννοώ πώς μετατρέπεται σε bytes, το int -> bits
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 15:28

Επειδή είναι union, αυτός είναι ο ρόλος του union.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 09 Σεπ 2011, 15:36

migf1 έγραψε:Επειδή είναι union, αυτός είναι ο ρόλος του union.

Και πού ξέρει ότι είναι bits; Από το όνομα του struct;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 15:52

Δεν πολυ-καταλαβαίνω τι με ρωτάς (είσαι πολύ λακωνικός). Υποψιάζομαι όμως πως δεν έχεις πιάσει τι ακριβώς κάνει το union. Το union είναι ένας τρόπος να εκφράσεις μια μεταβλητή σε πολλούς τύπους δεδομένων, με την προϋπόθεση πως υπάρχει λογική αντιστοίχιση μεταξύ τους . Π.χ...

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

#include <stdio.h>

typedef union manytypes {
long int longtype;
int intype;
char chartype;
} ManyTypes;

// -------------------------------------------------------------------------------------------------------
int main( void )
{
ManyTypes var;

var.inttype = 65;
...
}

Η τιμή 65 ανατέθηκε ως int στο .intype αλλά ταυτόχρονα ενημερώθηκαν και τα υπόλοιπα πεδία του union. Οπότε το 65 αυτό μπορείς να το διαχειριστείς σαν να το είχες περάσει ως οποιονδήποτε από τους 3 τύπους που έχεις ορίσει στο union, χρησιμοποιώντας το αντίστοιχο πεδίο.

Π.χ. μπορείς να περάσεις το χαρακτήρα 'Α' στο var.chartype και κατόπιν να τον διαχειρίζεσαι σαν να ήταν long χρησιμοποιώντας το var.longtype (αντί του var.chartype με το οποίο διάβασες αρχικά τον χαρακτήρα).

ΥΓ1. Βέβαια στη πράξη πρέπει να προσέχεις τα πεδία που βάζεις μέσα στο union να έχουν ίδιο μέγεθος ή έστω ο κώδικάς σου να κάνει σχετικούς ελέγχους. Για παράδειγμα, αν διαβάσεις μέσω του var.longtype την τιμή 2345678 και μετά πας να την εξετάσεις μέσω του var.chartype θα έχεις πρόβλημα, διότι δεν υπάρχει χαρακτήρας με τέτοιο ASCII code... το πολύ μέχρι 255 είναι τα ASCI codes... (0-255 είναι οι τιμές που μπορούν να απεικονιστούν σε ένα byte).

ΥΓ2. Λοιπόν, αισθάνομαι ότι σας βομβάρδισα πολύ ξαφνικά με πολύ πράγμα και μάλλον δεν ήταν καλή ιδέα. Θέλετε να δώσω και τον portable κώδικα για διαχείριση διευθύνσεων δεικτών κι ότι καταλάβετε, και να επιστρέψουμε στα strings; Ή αν έχετε βαρεθεί τα strings να πούμε για δομές (struct) ;
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 09 Σεπ 2011, 15:59

Ενννούσα ότι δεν καταλαβαίνω πώς ξέρει ο υπολογιστής ότι το struct Bits και τα μεταχειρίζεται :problem:
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 09 Σεπ 2011, 16:03

Επειδή το value και το bits είναι πεδία ενός union, άρα μοιράζονται την ίδια περιοχή μνήμης... αυτό κάνει το union, όλα τα πεδία του μοιράζονται την ίδια περιοχή μνήμης.

Κώδικας: Επιλογή όλων
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;

Άρα το .value και το .bits μοιράζονται την ίδια μνήμη, την οποία μνήμη μπορείς να την καλέσεις είτε γράφοντας: .value είτε .bits.bX
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι