AfterForever Δημοσ. 8 Ιουλίου 2017 Δημοσ. 8 Ιουλίου 2017 Καλησπέρα. Έχω να τα πιάσω χρόνια και κάπου το χάνω. unsigned char x; x = 178; x = x & 0x74; x = x | 0xD6; x = x ^ 104; x = x >> 3; x = x << 2; x = ~x; Καταρχάς δεδομένου ότι το έχει δηλώσει unsigned char σημαίνει ότι παίρνει τιμές 0-255. Μετά κάνει τους bitwise operators. Εγώ αυτό που κάνω είναι: στην αρχή το χ παίρνει τη δεκαδική τιμή 178. τη μετατρέπω σε δυαδική. μετά κάνει and με τον δεκαεξαδικό 74. οπότε τον μετατρέπω σε δυαδικό και κάνω το AND ανά ψηφίο. μετά κάνει or με τον δεκαδικό 104, τον μετατρέπω σε δυαδικό και κάνω το or ανα ψηφίο. μετά 3 ολισθήσεις δεξιά και 2 αριστερά. Πρακτικά στις 3 ολισθήσεις πρόσθεσα 3 μηδενικά αριστερά και έσβησα τα 3 τελευταία ψηφία. Στον αριθμό που προέκυψε ομοίως ολίσθηση 2 ψηφία αριστερά. Πρόσθεσα 2 μηδενικά στο τέλος και έσβησα τα 2 πρώτα. Εν τέλει στο not, όπου 0 έβαλα 1 και αντίστροφα. Στο τέλος που κάνω printf("%d",x); μου εμφανίζει τον 179. Όταν το κάνω στο χαρτί, μου εμφανίζονται άλλα αντί άλλων. Ως μεθοδολογία τα σωστά βήματα ακολουθώ; Γιατί αν ναι κάνω κάπου λάθος στις πράξεις. Ευχαριστώ.
Ilias95 Δημοσ. 8 Ιουλίου 2017 Δημοσ. 8 Ιουλίου 2017 Στο τέλος που κάνω printf("%d",x); μου εμφανίζει τον 179. Γιατί δεν το κάνεις ανα βήμα αυτό για να δεις τι γίνεται; Ή ακόμα καλύτερα να το τρέξεις στον gdb;
imitheos Δημοσ. 8 Ιουλίου 2017 Δημοσ. 8 Ιουλίου 2017 Καλησπέρα. Έχω να τα πιάσω χρόνια και κάπου το χάνω. unsigned char x; x = 178; x = x & 0x74; x = x | 0xD6; x = x ^ 104; x = x >> 3; x = x << 2; x = ~x; Καταρχάς δεδομένου ότι το έχει δηλώσει unsigned char σημαίνει ότι παίρνει τιμές 0-255. Μετά κάνει τους bitwise operators. Εγώ αυτό που κάνω είναι: στην αρχή το χ παίρνει τη δεκαδική τιμή 178. τη μετατρέπω σε δυαδική. μετά κάνει and με τον δεκαεξαδικό 74. οπότε τον μετατρέπω σε δυαδικό και κάνω το AND ανά ψηφίο. μετά κάνει or με τον δεκαδικό 104, τον μετατρέπω σε δυαδικό και κάνω το or ανα ψηφίο. μετά 3 ολισθήσεις δεξιά και 2 αριστερά. Πρακτικά στις 3 ολισθήσεις πρόσθεσα 3 μηδενικά αριστερά και έσβησα τα 3 τελευταία ψηφία. Στον αριθμό που προέκυψε ομοίως ολίσθηση 2 ψηφία αριστερά. Πρόσθεσα 2 μηδενικά στο τέλος και έσβησα τα 2 πρώτα. Εν τέλει στο not, όπου 0 έβαλα 1 και αντίστροφα. Στο τέλος που κάνω printf("%d",x); μου εμφανίζει τον 179. Όταν το κάνω στο χαρτί, μου εμφανίζονται άλλα αντί άλλων. Ως μεθοδολογία τα σωστά βήματα ακολουθώ; Γιατί αν ναι κάνω κάπου λάθος στις πράξεις. Ευχαριστώ. Αν και φαίνεται για άσκηση, ας το δούμε. unsigned char x; x = 178; x = x & 0x74; Το 0x74 είναι 116 δηλαδή 1110100 και το 178 είναι 10110010. Η πράξη AND δίνει αποτέλεσμα 1 αν και μόνο και τα δύο ορίσματα είναι 1. 10110010 & 01110100 ------------ 00110000 Οπότε το x αυτή την στιγμή έχει τιμή 32 + 16 = 48. x = 48; x = x | 0xD6; Η πράξη OR δίνει αποτέλεσμα 1 αν τουλάχιστον 1 όρισμα είναι 1. Επίσης το 0xD6 είναι 214 δηλαδή 11010110. 00110000 | 11010110 ------------ 11110110 Έτσι το x έχει τιμή 128+64+32+16+4+2 = 246 x = 246; x = x ^ 104; Η πράξη Exclusive OR δίνει αποτέλεσμα 1 αν μόνο ένα όρισμα είναι 1 (ή αν το θες διαφορετικά μόνο όταν τα ορίσματα διαφέρουν). Το 104 είναι 1101000. 11110110 ^ 01101000 ------------ 10011110 Ετσι το x έχει τιμή 128+16+8+4+2=158. x = 158; x = x >> 3; x = x << 2; Το 10011110 θα γίνει shift 3 φορές δεξιά και μετά 2 φορές αριστερά. Δηλαδή θα γίνει 10011 (19) και μετά 1001100 (76). Ο τύπος της μεταβλητής είναι unsigned και έχουμε μικρά shifts οπότε δεν έχουμε απροσδιόριστη συμπεριφορά. x = 76; x = ~x; Αντιστρέφεις κάθε bit από τον αριθμό 76 και αποθηκεύεις το αποτέλεσμα στον x. Έτσι λοιπόν το 1001100 θα γίνει 111111...0110011 (όσα 1 χρειάζεται για ένα int) και μετά το αποτέλεσμα που θα έχει ο x θα είναι 10110011 δηλαδή 128 + 32 + 16 + 2 + 1 = 179 όπως το έβγαλες. 1
AfterForever Δημοσ. 8 Ιουλίου 2017 Μέλος Δημοσ. 8 Ιουλίου 2017 Σε ευχαριστώ πάρα πολύ. Ακολούθησα τα ίδια με τη διαφορά ότι χρησιμοποίησα online bitwise calculators και όντως έβγαιναν έτσι. Άρα προφανώς έκανα κάποια τραγική κουταμάρα στις πράξεις που δεν την έχω πάρει πρέφα. Με ενδιέφερε πιο πολύ αν ακολουθούσα τη σωστή μεθοδολογία. Και πάλι ευχαριστώ.
imitheos Δημοσ. 8 Ιουλίου 2017 Δημοσ. 8 Ιουλίου 2017 Σε ευχαριστώ πάρα πολύ. Ακολούθησα τα ίδια με τη διαφορά ότι χρησιμοποίησα online bitwise calculators και όντως έβγαιναν έτσι. Άρα προφανώς έκανα κάποια τραγική κουταμάρα στις πράξεις που δεν την έχω πάρει πρέφα. Με ενδιέφερε πιο πολύ αν ακολουθούσα τη σωστή μεθοδολογία. Και πάλι ευχαριστώ. Διαβάζοντας ξανά το αρχικό σου μήνυμα, βλέπω ότι γράφεις "κάνει or με τον δεκαδικό 104". Ίσως εδώ να έκανες λάθος γιατί η πράξη είναι XOR και όχι OR. Μια άλλη παγίδα είναι όταν μπλέκεις πολλούς τελεστές μαζί. Μέχρι να μάθεις κάποια πράγματα, οποτεδήποτε έχεις να χρησιμοποιήσεις bitwise τελεστές, να κάνεις μόνο μία πράξη σε κάθε δήλωση, όπως δηλαδή είχε και η άσκηση. Δεν ξέρω αν πρόσεξες αυτό που είπα πριν για το "όσα χωράνε σε ένα int". Η C ΔΕΝ κάνει πράξεις με μικρότερους τύπους από int. Υπάρχει το λεγόμενο integer promotion το οποίο ορίζει ότι όλες οι πράξεις με τύπους μικρότερους από int γίνονται με int. Τι μας πειράζει τώρα αυτό ? unsigned char x; x = 76; x = ~x; printf("x=%d\n", x); x = x >> 1; printf("x=%d\n", x); x = 76; x = (~x) >> 1; printf("x=%d\n", x); Έξοδος: % ./a.out x=179 x=89 x=217 Ας πάρουμε το τελευταίο κομμάτι της άσκησής σου. Είχαμε τον αριθμό 76, παίρναμε το συμπλήρωμά του ως προς 1 και έβγαινε 179. Αν μετά κάνω δεξί shift κατά 1 παίρνω 89 το οποίο είναι λογικό. Το 10110011 που είναι το 179 θα ολισθήσει δεξιά και θα γίνει 01011001 δηλαδή 89. Γιατί τότε όταν κάνω τις ίδιες ακριβώς πράξεις σε μία δήλωση παίρνω 217 ? Η μεταβλητή x έχει τύπο unsigned char δηλαδή τύπο μικρότερο από int οπότε στην έκφραση ~x, θα έχω integer promotion και το x θα μεταχειριστεί σαν να έχω int. Έτσι το 76 (1001100) θα γίνει 111..10110011 και μετά θα ολισθήσει μία θέση δεξιά. Επειδή έχουμε τύπο με πρόσημο, το >> θα πραγματοποιήσει αριθμητική ολίσθηση και θα μεταφέρει το κρατούμενο (δεν είναι σίγουρο ότι θα γίνει πάντα έτσι και εξαρτάται από την αρχιτεκτονική αλλά σε x86 που έχουμε εμείς θα γίνει έτσι) και θα πάρουμε τον αριθμό 1111..1011001 ο οποίος θα αποθηκευτεί στην μεταβλητή x (σαν 11011001 που είναι όσο χωράει η x). Επειδή όμως η x είναι unsigned, θα έχουμε την τιμή 217. Λόγω δηλαδή της integer promotion θα έχουμε λάθος τιμή στο τελευταίο bit. 3
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα