Câmp de biți ( câmp de biți ing. ) în programare - un număr de biți aranjați secvențial în memorie , a căror valoare procesorul nu este capabil să o citească din cauza particularităților implementării hardware .
Dacă este necesar să citiți valoarea scrisă în locația de memorie , procesorul efectuează următoarele acțiuni:
Valoarea citită este egală cu valoarea din locația de memorie specificată și are o dimensiune egală cu lățimea magistralei de date ( dimensiunea cuvântului mașinii ).
Lățimea magistralei de adrese determină dimensiunea minimă a memoriei adresabile . Controlerul de memorie necesită ca adresa celulei să fie aliniată la granița unui cuvânt de mașină .
Dacă lățimea de biți (numărul de biți) a valorii de citit (a unui câmp de biți) nu este egală cu dimensiunea cuvântului de mașină , după citirea cuvântului de mașină din memorie , trebuie executate instrucțiuni suplimentare :
Exemplu. Lăsa:
Dacă adresa valorii care urmează să fie citită din memorie nu este aliniată la granița unui cuvânt de mașină , sunt necesari pași suplimentari:
Exemplu. Lăsa:
Se pot efectua pașii suplimentari descriși:
Dezavantaj: comenzile suplimentare încetinesc execuția programului . Avantaj: atunci când se utilizează câmpuri de biți, se obține cea mai densă împachetare a informațiilor .
În general, compilatoarele permit numai următoarele operații pe câmpuri de biți:
Câmpul de biți în sine este tratat de compilator ca un număr fără semn . Ordinea câmpurilor de biți în structura datelor depinde de platforma hardware și de implementarea compilatorului : unii compilatori plasează câmpurile de biți pornind de la biții mai puțin semnificativi, în timp ce alții le plasează de la cei mai semnificativi.
Câmpurile de biți sunt folosite pentru cel mai complet pachet de informații , dacă viteza de acces la aceste informații nu este importantă. De exemplu, pentru a crește lățimea de bandă a canalului atunci când se transmite informații prin rețea sau pentru a reduce dimensiunea informațiilor în timpul stocării. De asemenea, utilizarea câmpurilor de biți este justificată dacă procesorul acceptă instrucțiuni specializate pentru lucrul cu câmpuri de biți, iar compilatorul utilizează aceste instrucțiuni atunci când generează codul mașinii .
De exemplu, pe mașinile cu un cuvânt de 32 de biți , toate câmpurile dintr-un pachet IPv4 (cu excepția câmpurilor „adresa expeditorului” și „adresa de destinație”) vor fi câmpuri de biți, deoarece dimensiunea lor nu este de 32 de biți și adresele lor nu sunt un multiplu de 4 octeți . Dacă, în plus, procesorul acceptă citirea și scrierea directă a numerelor de 8 și 16 biți, singurele câmpuri de biți vor fi versiunea, dimensiunea antetului, DSCP , ECN , steagurile și decalajul fragmentului.
Să fie câmpuri de patru biți într-un octet:
Număr de biți | 7 [*1] | 6 | 5 | patru | 3 | 2 | unu | 0 [*2] |
---|---|---|---|---|---|---|---|---|
câmp de biți | d | c | b | A | ||||
Valoarea unui număr de opt biți x , compus din câmpurile de biți a , b , c și d , poate fi calculată folosind formula: (1) .
Dacă a=1 , b=0 , c=2=10 2 și d=5=0101 2 , x va fi .
Dacă procesorul funcționează cu numere binare , formula (1) poate fi optimizată . După înlocuirea operațiilor „ exponentiare ” cu „ deplasare logică ”, „ adăugare ” cu „ bit SAU ”, formula (1) va lua forma:
x = ( d << 4 ) | ( c << 2 ) | ( b << 1 ) | ADeplasarea logică a unui număr binar este echivalentă cu înmulțirea/împărțirea cu un multiplu al unei puteri de doi: 2 1 =2, 2 2 =4, 2 3 =8 etc.
Există două moduri de a obține valoarea v a unui câmp de biți al numărului x :
Prima metodă efectuează mai întâi o operație AND pe biți , apoi o deplasare logică la dreapta. În a doua metodă, operațiile sunt efectuate în ordine inversă. Masca constantă_2 poate fi obținută din masca constantă_1 : . offset este numărul primului bit cel mai puțin semnificativ al câmpului de biți v , exponentul din formula (1) .
mask_2 = mask_1 >> offset
Pentru a obține valoarea unui câmp de biți din numărul x în primul mod, se efectuează trei operații:
Număr de biți | 7 | 6 | 5 | patru | 3 | 2 | unu | 0 |
---|---|---|---|---|---|---|---|---|
masca pentru a | 0 | 0 | 0 | 0 | 0 | 0 | 0 | unu |
masca pentru b | 0 | 0 | 0 | 0 | 0 | 0 | unu | 0 |
masca pentru c | 0 | 0 | 0 | 0 | unu | unu | 0 | 0 |
masca pentru d | unu | unu | unu | unu | 0 | 0 | 0 | 0 |
câmp de biți | decalaj |
---|---|
A | 0 |
b | unu |
c | 2 |
d | patru |
Un exemplu de obținere a unei valori dintr-un câmp de biți c :
c = ( x & 00001100 b ) >> 2Cu a doua metodă:
Număr de biți | 7 | 6 | 5 | patru | 3 | 2 | unu | 0 |
---|---|---|---|---|---|---|---|---|
masca pentru a | 0 | 0 | 0 | 0 | 0 | 0 | 0 | unu |
masca pentru b | 0 | 0 | 0 | 0 | 0 | 0 | 0 | unu |
masca pentru c | 0 | 0 | 0 | 0 | 0 | 0 | unu | unu |
masca pentru d | 0 | 0 | 0 | 0 | unu | unu | unu | unu |
Un exemplu de obținere a unei valori dintr-un câmp de biți c :
c = ( x >> 2 ) & 00000011 bCâmpul de biți cel mai puțin semnificativ (câmpul a în acest exemplu) nu este deplasat logic cu zero biți. Exemplu:
a = ( x & 00000001b ) >> 0
a = ( x >> 0 ) & 00000001b )
În a doua metodă, câmpul cel mai înalt (câmpul d din acest exemplu) nu efectuează înmulțirea logică, deoarece operația logică de deplasare la dreapta adaugă zero biți la număr. Exemplu:
d = ( x >> 4 ) & 00001111b )
Pentru a înlocui un câmp de biți, sunt efectuate trei operații:
Un exemplu de înlocuire a unei valori pentru un câmp de biți d :
xnew = ( x & 00001111 b ) | ( d << 4 )Există metode mai simple de lucru cu câmpuri de biți care au un bit lățime.
Câmpurile de biți a și b ocupă câte un bit.
Pentru a obține valoarea unui singur bit, se realizează o multiplicare logică (operație „ bit AND ”) a numărului x printr-o mască care are un bit setat, corespunzător unui bit dintr-un câmp de un bit. Dacă rezultatul este 0, bitul este 0.
Un exemplu de obținere a valorii unui câmp de un bit b :
b = ( ( x & 00000010 b ) != 0 )Pentru a verifica dacă unul sau mai mulți biți din grup sunt egali cu unul, se ia o mască, în care unitățile sunt setate în pozițiile biților bifați:
a_sau_b = ( ( x & 00000011 b ) != 0 )Pentru a verifica dacă toți biții din grup sunt egali cu unul, utilizați „ ȘI pe biți ” și operația „ == ” :
a_and_b = ( ( x & 00000011 b ) == 00000011 b )Pentru a seta biții, se efectuează o adăugare logică (operația „ bit SAU ”) a numărului x cu o mască care îi are setați în pozițiile corespunzătoare câmpului de biți.
Un exemplu de setare a unui pic dintr-un câmp de un bit a :
x1 = x | 00000001b _Pentru a seta mai mulți biți ai numărului x , de exemplu, biții câmpurilor de un bit a și b , utilizați o mască care are biți corespunzători biților câmpurilor de biți setate la uni:
x2 = x | 00000011b _Pentru a seta unul sau mai mulți biți de zerouri, numărul x este înmulțit cu operația „ bit AND ” de către mască, în care biții zero sunt setați în pozițiile corespunzătoare câmpului de biți.
Un exemplu de setare a biților la zero în câmpul de biți b :
x3 = x & 11111101 bPentru a schimba valoarea biților la opus (de la 0 la 1 și de la 1 la 0), numărul x se adaugă prin operația „ SAU exclusiv de biți ” cu o mască în care unitățile sunt setate în poziții corespunzătoare pozițiilor de biții de comutare.
Un exemplu de modificare a valorilor biților din câmpul de biți b :
x4 = x ^ 00000010b _În memoria computerului, numerele întregi negative pot fi codificate în unul dintre următoarele moduri:
Majoritatea procesoarelor moderne implementează a treia metodă. Luați în considerare reprezentarea binară a mai multor numere întregi în complement a doi :
4 = 00000100 2 3 = 00000011 2 2 = 00000010 2 1 = 00000001 2 0 = 00000000 2 -1 = 11111111 2 -2 = 11111112 = 11111112 = 10111112 = 10111110111111111101 etc.Fie că câmpurile c și d au formatul „ cod complementar ”. Atunci câmpul c poate stoca numere de la −2=10 2 la 1=01 2 , iar câmpul d poate stoca numere de la −8=1000 2 la 7=0111 2 .
Fiecare dintre termeni (cu excepția celui mai înalt), pentru a nu strica biții mai mari, trebuie înmulțit cu o mască de biți de lungimea corespunzătoare. În special:
x = (d << 4) + ((c & 00000011b) << 2) + (b << 1) + aPentru a extrage numere, trebuie să mutați câmpul cu numărul necesar de biți la dreapta, înmulțind în același timp bitul de semn. De exemplu, puteți utiliza schimbarea aritmetică pentru a face acest lucru . Dacă x are 8 biți lungime, atunci
c = (x << 4 ) >>a 6 d = x >>a 4Atenţie! În limbajul de programare Java , opusul este adevărat: semnul denotă o schimbare aritmetică , iar semnul denotă o schimbare logică . >>>>>
Dacă nu există o schimbare aritmetică, atunci...
c1 = x >> 2 dacă (c1 și 00000010b ≠ 0) atunci c = c1 | 0x11111100b în caz contrar c = c1 & 0x00000011bÎn C și C++ , la declararea unui câmp de biți , este folosit caracterul două puncte ( :) . Coloana este urmată de o expresie constantă care determină numărul de biți din câmpul de biți [1] . Exemplu:
struct rgb { nesemnat r : 3 ; nesemnat g : 3 ; nesemnat b : 3 ; };