vec#
Διαβάζει ή γράφει μια θυρίδα σταθερού πλάτους μέσα σε μια συμβολοσειρά που αντιμετωπίζεται ως πακεταρισμένο διάνυσμα bits.
Η vec θεωρεί την EXPR ως πίνακα μη προσημασμένων ακεραίων, καθένας με πλάτος BITS, πακεταρισμένων ο ένας μετά τον άλλο από την αρχή της συμβολοσειράς. Το OFFSET ευρετηριάζει σε αυτόν τον πίνακα - όχι σε bytes, όχι σε bits, αλλά σε στοιχεία μεγέθους BITS. Η μορφή ανάγνωσης επιστρέφει τον ακέραιο σε αυτή τη θυρίδα· η μορφή lvalue γράφει έναν. Τα πλάτη είναι 1, 2, 4, 8, 16, 32, και σε builds 64-bit το 64.
Σύνοψη#
my $n = vec($buf, $offset, $bits);
vec($buf, $offset, $bits) = $n;
Τι επιστρέφεται#
Σε rvalue περιβάλλον, έναν μη προσημασμένο ακέραιο - τα περιεχόμενα της επιλεγμένης θυρίδας, επεκταμένα με μηδενικά σε αριθμό της Perl. Σε lvalue περιβάλλον, μια εκχωρήσιμη θυρίδα· η εκχώρηση αποκόπτει τη δεξιά τιμή σε BITS και τη γράφει στη συμβολοσειρά, επεκτείνοντας τη συμβολοσειρά με μηδενικά bytes αν το OFFSET βρίσκεται πέρα από το τρέχον τέλος.
Οι παρενθέσεις γύρω από το vec(...) στη μορφή lvalue είναι απαραίτητες - χωρίς αυτές, το vec $buf, $o, $b = 3 αναλύει το = ως μέρος της λίστας ορισμάτων.
Πώς διατάσσονται τα bits#
Η διάταξη εξαρτάται από τα BITS, και επιλέγεται ώστε ο κώδικας να είναι φορητός μεταξύ μηχανών big- και little-endian:
BITS == 8: κάθε θυρίδα είναι ένα byte της συμβολοσειράς. Τοvec($s, $i, 8)είναι η μη προσημασμένη τιμή τουsubstr($s, $i, 1).BITS == 16,32,64: τα bytes της συμβολοσειράς ομαδοποιούνται σε κομμάτια τωνBITS/8και ερμηνεύονται σε σειρά big-endian - ισοδύναμο με τηνunpackμεn,N, ή (σε builds 64-bit)Q>/ το ηθικό ισοδύναμο. Τοvec($s, 0, 32)διαβάζει τα πρώτα τέσσερα bytes ως big-endianuint32.BITS == 4, 2, 1: η συμβολοσειρά σπάει σε bytes, και κάθε byte χωρίζεται σε8/BITSομάδες, αριθμημένες little-endian-ish εντός του byte. Οι τιμές bit από χαμηλό σε υψηλό είναι0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80. Έτσι για τοchr(0x36)(0b00110110):Το
BITS == 4δίνει τα δύο nibbles(0x6, 0x3).Το
BITS == 2δίνει τις τέσσερις ομάδες των 2 bits(0x2, 0x1, 0x3, 0x0).Το
BITS == 1δίνει τα οκτώ bits(0, 1, 1, 0, 1, 1, 0, 0).
Μια θυρίδα εντελώς εκτός του τέλους της συμβολοσειράς διαβάζεται ως 0. Η εγγραφή πέρα από το τέλος μεγαλώνει τη συμβολοσειρά με μηδενικά bytes για να φτάσει τη θυρίδα. Ένα αρνητικό OFFSET είναι μοιραίο σφάλμα.
Καθολική κατάσταση που επηρεάζει#
Καμία. Η vec λειτουργεί καθαρά επί των ορισμάτων της.
Παραδείγματα#
Διαβάστε ένα byte σε δοσμένο δείκτη:
my $s = "Perl";
print vec($s, 0, 8); # 80 (== ord 'P')
print vec($s, 3, 8); # 108 (== ord 'l')
Κατασκευάστε μια συμβολοσειρά γράφοντας λέξεις 32-bit big-endian:
my $buf = '';
vec($buf, 0, 32) = 0x5065726C; # "Perl"
vec($buf, 1, 32) = 0x50657270; # "PerlPerp"
print $buf; # PerlPerp
Χρησιμοποιήστε τη vec ως συμπαγή πίνακα λογικών τιμών - ένα bit ανά σημαία:
my $flags = '';
vec($flags, 17, 1) = 1;
vec($flags, 42, 1) = 1;
print vec($flags, 17, 1); # 1
print vec($flags, 18, 1); # 0 (slot never set, still zero)
print length $flags; # 6 (string auto-extended to fit bit 42)
Μετρήστε τα ενεργοποιημένα bits σε διάνυσμα bits χωρίς βρόχο bit-προς-bit - το ιδιωματικό μοτίβο χρησιμοποιεί την unpack:
my $ones = unpack("%32b*", $flags); # population count
Μετατρέψτε ένα διάνυσμα bits σε συμβολοσειρά από 0 και 1 για εμφάνιση:
my $bits = unpack("b*", $flags); # "00...010...010..."
Συνδυάστε δύο διανύσματα bits με τους bitwise τελεστές συμβολοσειρών - αυτοί αντιμετωπίζουν τους τελεστέους συμβολοσειρών ως διανύσματα bits του ίδιου σχήματος που διαβάζει και γράφει η vec:
my $union = $flags_a | $flags_b;
my $intersection = $flags_a & $flags_b;
my $diff = $flags_a ^ $flags_b;
Οριακές περιπτώσεις#
Προτεραιότητα lvalue: το
vec EXPR, O, B = Nείναι συντακτικό σφάλμα. Γράφετε πάνταvec(EXPR, O, B) = N.Ανάγνωση εκτός του τέλους: η
vec($short, 1_000_000, 8)επιστρέφει0, ποτέ δεν πεθαίνει, ποτέ δεν προειδοποιεί.Εγγραφή εκτός του τέλους: η συμβολοσειρά συμπληρώνεται με μηδενικά έως τη θυρίδα. Για
BITS == 1, η εγγραφή του bit 94 μεγαλώνει τη συμβολοσειρά στα 12 bytes.Αρνητικό
OFFSET: μοιραίο -"Negative offset to vec in lvalue context"ή το ισοδύναμο rvalue.Τα
BITSδεν είναι υποστηριζόμενη δύναμη του δύο: μοιραίο με"Illegal number of bits in vec". Έγκυρα πλάτη είναι 1, 2, 4, 8, 16, 32, και 64 σε builds 64-bit.Συμβολοσειρές κωδικοποιημένες σε UTF-8: η
vecθέλει συμβολοσειρά bytes. Αν το βαθμωτό φέρει τη σημαία UTF-8, η Perl προσπαθεί πρώτα να το υποβιβάσει σε αναπαράσταση ενός byte ανά χαρακτήρα. Αν κάποιος χαρακτήρας έχει codepoint 256 ή υψηλότερο, αυτό αποτυγχάνει μοιραία με"Wide character in vec". Καλέστε τηνutf8::downgradeσκόπιμα, ή πακετάρετε τα δεδομένα πρώτα μεpack"C*", πριν προστρέξετε στηvec.Ανάγνωση σε
undef: υπόuse warnings, ενεργοποιεί προειδοποίησηuninitializedστο όρισμα συμβολοσειράς· επιστρέφει0.Τιμή εκχώρησης πλατύτερη από τα
BITS: η τιμή μασκάρεται στα κατώτεραBITSbits. Τοvec($s, 0, 4) = 0x1Fαποθηκεύει0xF.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
pack- κατασκευάστε δυαδικές δομές πολλαπλών πεδίων· ηvecείναι το αντίστοιχο τυχαίας πρόσβασης όταν κάθε πεδίο έχει το ίδιο πλάτοςunpack- εξαγάγετε πεδία από δυαδική συμβολοσειρά· χρησιμοποιήστεunpack("b*", $v)ήunpack("%32b*", $v)για να αποδώσετε ή να μετρήσετε popcount ενός διανύσματος bits τηςvecsubstr- τυχαία πρόσβαση σε επίπεδο byte όταν ταBITSθα ήταν8και θέλετε επίσης η lvalue να μεγαλώσει ή να συρρικνώσει τη συμβολοσειράsprintf- μορφοποιήστε τον ακέραιο που επιστρέφει μια ανάγνωσηvec, π.χ.sprintf "%08b", vec($s, $i, 8)ord- ισοδύναμο μίας εκτέλεσης τηςvec($s, $i, 8)όταν χρειάζεστε μόνο την τιμή byte και ποτέ δεν εκχωρείτε πίσω