Usa Bitmask in C++
-
Usa
struct
per definire la maschera di bit e implementare l’oggetto data in C++ -
Usa
struct
eunion
per definire la maschera di bit e implementare l’oggetto data in C++ -
Usa
std::bitset
per definire la maschera di bit in C++
Questo articolo illustrerà più metodi su come utilizzare la maschera di bit in C++.
Usa struct
per definire la maschera di bit e implementare l’oggetto data in C++
struct
è una struttura dati popolare in C++. Inoltre, è solo leggermente diverso dalla class
rispetto al linguaggio C. In questo caso, abbiamo solo bisogno di definire struct
con diversi membri dati, ma c’è una nuova notazione :
usata dopo ogni nome di variabile e un numero intero specificato. Come mostrato nel codice di esempio, abbiamo dichiarato una struct
con membri di dati di tipo uint32_t
e la somma dei numeri a destra è 32. Questa costruzione implica che la struct
occupa la dimensione di un singolo uint32_t
tipo di dati in memoria e l’utente può accedere ai suoi intervalli di bitfield (23:5:4) separatamente.
Questo metodo viene utilizzato principalmente per risparmiare l’utilizzo della memoria di strutture di dati che potrebbero essere compresse in strutture
simili. È anche uno dei modi più comuni per accedere a dati più piccoli di un byte nel linguaggio di programmazione C++. Nota che il primo membro anno
può contenere solo valori interi fino a 223-1 e gli altri membri seguono in modo simile.
#include <iostream>
using std::cout;
using std::endl;
struct {
uint32_t year : 23;
uint32_t day : 5;
uint32_t month : 4;
} typedef Bitfield;
int main() {
Bitfield date = {2020, 13, 12};
cout << "sizeof Bitfield: " << sizeof(date) << " bytes\n";
cout << "date: " << date.day << "/" << date.month << "/" << date.year << endl;
return EXIT_SUCCESS;
}
Produzione:
sizeof Bitfield: 4 bytes
date: 13/12/2020
Usa struct
e union
per definire la maschera di bit e implementare l’oggetto data in C++
Il metodo precedente è un modo sufficiente e corretto per implementare la maschera di bit. Tuttavia, ha uno svantaggio: l’accesso e l’assegnazione di valori ai membri richiede relativamente più tempo rispetto alle operazioni sui tipi incorporati. Questo può essere risolto implementando un oggetto di tipo union
costituito da una struct
e da una singola variabile di tipo incorporata. Notare che struct
è il layout è lo stesso che costruiremmo nel metodo precedente. In questo caso, la differenza è la variabile uint32_t ydm
che occupa la stessa dimensione della struct
.
L’idea è di inizializzare / assegnare ai membri dei dati i loro valori molto più velocemente. Vale a dire, costruiamo un intero con operazioni bit per bit che corrispondono esattamente alla disposizione dei bit quando sono memorizzati nella struct
e poi lo assegniamo a un singolo membro uint32_t
. Ciò consente di risparmiare tempo per accedere ai dati una volta anziché ripetere la stessa operazione per ciascuno dei tre membri.
L’aritmetica bit per bit è relativamente semplice; vale a dire, iniziamo con il valore del primo membro nella struct
, che viene modificato in OR con il risultato del membro successivo spostato a sinistra del numero di bit occupati dal membro precedente, e segue in modo simile.
#include <iostream>
using std::cout;
using std::endl;
union BitfieldFast {
struct {
uint32_t year : 23;
uint32_t day : 5;
uint32_t month : 4;
};
uint32_t ydm;
};
int main() {
BitfieldFast date_f{};
date_f.ydm = 2020 | (13 << 23) | (12 << 28);
cout << "sizeof BitfieldFast: " << sizeof(date_f) << " bytes\n";
cout << "date: " << date_f.day << "/" << date_f.month << "/" << date_f.year
<< endl;
return EXIT_SUCCESS;
}
sizeof BitfieldFast: 4 bytes
date: 13/12/2020
Usa std::bitset
per definire la maschera di bit in C++
std::bitset
è una caratteristica della libreria standard che include la classe per memorizzare i dati della maschera binaria. bitset
ha più utili funzioni di manipolazione integrate e la dichiarazione è abbastanza semplice. Può essere inizializzato con un valore di stringa binaria o più valori numerici. Le operazioni bit per bit sono metodi incorporati e possono essere chiamate con operatori tradizionali sovraccaricati. Notare che, il metodo reset
modifica permanentemente il bitset
da cui viene chiamato.
#include <bitset>
#include <iostream>
using std::cout;
using std::endl;
int main() {
std::bitset<16> bs1("1100100011110010");
std::bitset<16> bs2(0xfff0);
cout << "bs1 : " << bs1 << endl;
cout << "bs2 : " << bs2 << endl;
cout << "NOT bs1 : " << ~bs1 << endl;
cout << "bs1 AND bs2: " << (bs1 & bs2) << endl;
cout << "bs1 reset : " << bs1.reset() << endl;
return EXIT_SUCCESS;
}
Produzione:
bs1 : 1100100011110010
bs2 : 1111111111110000
NOT bs1 : 0011011100001101
bs1 AND bs2: 1100100011110000
bs1 reset : 0000000000000000
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook