Bittikenttä ( eng. bit field ) ohjelmoinnissa - joukko bittejä , jotka on järjestetty peräkkäin muistiin , jonka arvoa prosessori ei pysty lukemaan laitteistototeutuksen erityispiirteiden vuoksi .
Jos muistipaikkaan kirjoitettu arvo on luettava , prosessori suorittaa seuraavat toimet:
Lukuarvo on yhtä suuri kuin määritetyn muistipaikan arvo, ja sen koko on yhtä suuri kuin tietoväylän leveys ( konesanan koko ).
Osoiteväylän leveys määrittää pienimmän osoitettavan muistin koon . Muistiohjain vaatii, että solun osoite on kohdistettu koneen sanarajalle .
Jos luettavan arvon (bittikentän) bittileveys (bittien lukumäärä) ei ole sama kuin konesanan koko, konesanan muistista lukemisen jälkeen on suoritettava lisäkäskyjä :
Esimerkki. Päästää:
0011 0100 1010 11 10 01 00 0111 0100 1100 2Jos muistista luettavan arvon osoitetta ei ole kohdistettu koneen sanarajaan , tarvitaan lisävaiheita:
Esimerkki. Päästää:
Kuvatut lisävaiheet voidaan suorittaa:
Haittapuoli: ylimääräiset komennot hidastavat ohjelman suorittamista . Etu: bittikenttiä käytettäessä saavutetaan tihein tiedon pakkaus .
Kääntäjät sallivat yleensä vain seuraavat toiminnot bittikentillä:
Kääntäjä käsittelee itse bittikenttää etumerkittömänä numerona . Bittikenttien järjestys tietorakenteessa riippuu laitteistoalustasta ja kääntäjän toteutuksesta : jotkut kääntäjät sijoittavat bittikentät vähiten merkitsevistä biteista alkaen, kun taas toiset sijoittavat ne merkittävimmistä.
Bittikenttiä käytetään tietojen täydellisimpään pakkaamiseen , jos näiden tietojen nopeus ei ole tärkeä. Esimerkiksi lisäämään kanavan kaistanleveyttä siirrettäessä tietoa verkon yli tai pienentämään tiedon kokoa tallennuksen aikana. Myös bittikenttien käyttö on perusteltua, jos prosessori tukee erikoisohjeita bittikenttien kanssa työskentelemiseen ja kääntäjä käyttää näitä ohjeita luodessaan konekoodia .
Esimerkiksi koneissa, joissa on 32-bittinen sana , kaikki IPv4 - paketin kentät (lukuun ottamatta kenttiä "lähettäjäosoite" ja "kohdeosoite") ovat bittikenttiä, koska niiden koko ei ole 32 bittiä ja osoitteet eivät ole . 4 tavun kerrannainen . Jos prosessori lisäksi tukee 8- ja 16-bittisten numeroiden suoraa lukemista ja kirjoittamista, ainoat bittikentät ovat versio, otsikon koko, DSCP , ECN , liput ja fragmenttisiirtymä.
Olkoon yhdessä tavussa neljä bittikenttää:
Bittinumero | 7 [*1] | 6 | 5 | neljä | 3 | 2 | yksi | 0 [*2] |
---|---|---|---|---|---|---|---|---|
bittikenttä | d | c | b | a | ||||
Kahdeksanbittisen luvun x arvo , joka koostuu bittikentistä a , b , c ja d , voidaan laskea kaavalla: (1) .
Jos a=1 , b=0 , c=2= 102 ja d=5= 01012 , x on .
Jos prosessori toimii binääriluvuilla , kaava (1) voidaan optimoida . Kun operaatiot " eksponentiointi " on korvattu " loogisella siirrolla ", " lisäys " bitillä OR , kaava (1) saa muotoa:
x = ( d << 4 ) | ( c << 2 ) | ( b << 1 ) | aBinääriluvun looginen siirtymä vastaa kertomista/jakamista kahden potenssin kerrannaisella: 2 1 =2, 2 2 =4, 2 3 =8 jne.
On kaksi tapaa saada luvun x jonkin bittikentän arvo v :
Ensimmäinen menetelmä suorittaa ensin bittikohtaisen AND -operaation ja sitten loogisen siirron oikealle. Toisessa menetelmässä toiminnot suoritetaan käänteisessä järjestyksessä. Vakio maski_2 saadaan vakiosta maski_1 : . offset on kaavan (1) eksponentin bittikentän v ensimmäisen vähiten merkitsevän bitin numero .
mask_2 = mask_1 >> offset
Bittikentän arvon saamiseksi luvusta x ensimmäisellä tavalla suoritetaan kolme toimintoa:
Bittinumero | 7 | 6 | 5 | neljä | 3 | 2 | yksi | 0 |
---|---|---|---|---|---|---|---|---|
naamio a | 0 | 0 | 0 | 0 | 0 | 0 | 0 | yksi |
maski b :lle | 0 | 0 | 0 | 0 | 0 | 0 | yksi | 0 |
maski c | 0 | 0 | 0 | 0 | yksi | yksi | 0 | 0 |
naamio d | yksi | yksi | yksi | yksi | 0 | 0 | 0 | 0 |
bittikenttä | offset |
---|---|
a | 0 |
b | yksi |
c | 2 |
d | neljä |
Esimerkki arvon saamisesta bittikentästä c :
c = ( x & 00001100 b ) >> 2Toisella menetelmällä:
Bittinumero | 7 | 6 | 5 | neljä | 3 | 2 | yksi | 0 |
---|---|---|---|---|---|---|---|---|
naamio a | 0 | 0 | 0 | 0 | 0 | 0 | 0 | yksi |
maski b :lle | 0 | 0 | 0 | 0 | 0 | 0 | 0 | yksi |
maski c | 0 | 0 | 0 | 0 | 0 | 0 | yksi | yksi |
naamio d | 0 | 0 | 0 | 0 | yksi | yksi | yksi | yksi |
Esimerkki arvon saamisesta bittikentästä c :
c = ( x >> 2 ) & 00000011 bVähiten merkitsevää bittikenttää (kenttä a tässä esimerkissä) ei ole loogisesti siirretty nollalla bitillä. Esimerkki:
a = ( x & 00000001b ) >> 0
a = ( x >> 0 ) & 00000001b )
Toisessa menetelmässä korkein kenttä ( tässä esimerkissä d -kenttä ) ei suorita loogista kertolaskua, koska looginen siirto oikealle lisää numeroon nolla bittiä. Esimerkki:
d = ( x >> 4 ) & 00001111b )
Bittikentän korvaamiseksi suoritetaan kolme toimintoa:
Esimerkki bittikentän d arvon korvaamisesta :
xuusi = ( x & 00001111 b ) | ( d << 4 )On olemassa yksinkertaisempia tapoja työskennellä yhden bitin leveiden bittikenttien kanssa.
Bittikentät a ja b vievät kukin yhden bitin.
Yhden bitin arvon saamiseksi suoritetaan luvun x looginen kertolasku (" bitti JA " -toiminto) maskilla, jossa on yksi bitti, joka vastaa yksibittisen kentän bittiä. Jos tulos on 0, bitti on 0.
Esimerkki yksibittisen kentän b arvon saamisesta :
b = ( ( x & 00000010 b ) != 0 )Sen tarkistamiseksi, onko yksi tai useampi bitti ryhmästä yhtä suuri kuin yksi, otetaan maski, jossa yksiköt asetetaan tarkistettujen bittien paikkoihin:
a_tai_b = ( ( x & 00000011 b ) != 0 )Tarkistaaksesi, ovatko kaikki ryhmän bitit yhtä suuria kuin yksi, käytä " bitwise AND " ja " == " -toimintoa :
a_ja_b = ( ( x & 00000011 b ) == 00000011 b )Bittien asettamiseksi suoritetaan luvun x looginen yhteenlasku (" bitt OR " -toiminto) maskilla, jonka bittikenttää vastaaviin paikkoihin on asetettu bittiä.
Esimerkki yhden bitin kentän bitin asettamisesta :
x1 = x | 00000001b _Jos haluat asettaa useita luvun x bittejä , esimerkiksi yksibittisten kenttien a ja b bittejä, käytä maskia, jossa bittikenttien bittejä vastaavat bitit on asetettu ykkösiksi:
x2 = x | 00000011b _Yhden tai useamman nollabitin asettamiseksi kerrotaan luku x maskin " bitti AND " -operaatiolla, jossa nollabitit asetetaan bittikenttää vastaaviin paikkoihin.
Esimerkki bittien asettamisesta nollaan bittikentässä b :
x3 = x & 11111101 bBittien arvon muuttamiseksi päinvastaiseksi (0:sta 1:een ja 1:stä 0:aan) numero x lisätään " bittiä poissulkevalla TAI " -operaatiolla maskilla, jossa yksiköt asetetaan paikkoihin, jotka vastaavat bitin paikkoja. vaihtobitit.
Esimerkki bittikentän b bittiarvojen muuttamisesta :
x4 = x ^ 00000010b _Tietokoneen muistissa negatiiviset kokonaisluvut voidaan koodata jollakin seuraavista tavoista:
Useimmat nykyaikaiset prosessorit käyttävät kolmatta menetelmää. Harkitse useiden kokonaislukujen binaariesitystä kahden komplementissa :
4 = 00000100 2 3 = 00000011 2 2 = 00000010 2 1 = 00000001 2 0 = 00000000 2 -1 = 11111111 2 -2 = 11111111 2 -2 = 11111111 2 -2 = 11111111 = 11111111 = 1 0 1 21 -1110 jne.Olkoon kenttien c ja d muotoa " täydentävä koodi ". Tällöin kenttään c voidaan tallentaa numeroita välillä −2=10 2 - 1=01 2 , ja kenttään d voidaan tallentaa numeroita välillä −8=1000 2 - 7=0111 2 .
Jokainen termi (paitsi korkein), jotta se ei pilaa korkeampia bittejä, on kerrottava sopivan pituisella bitimaskeella. Erityisesti:
x = (d << 4) + ((c & 00000011b) << 2) + (b << 1) + aLukujen poimimiseksi sinun on siirrettävä kenttää tarvittavalla määrällä bittejä oikealle, kertomalla samalla etumerkkibitti. Voit tehdä tämän esimerkiksi käyttämällä aritmeettista siirtoa . Jos x on 8 bittiä pitkä, niin
c = (x << 4 ) >>a 6 d = x >>a 4Huomio! Java -ohjelmointikielessä asia on päinvastoin: merkki tarkoittaa aritmeettista muutosta ja merkki loogista muutosta . >>>>>
Jos aritmeettista muutosta ei ole, niin...
c1 = x >> 2 jos (c1 & 00000010b ≠ 0) sitten c = c1 | 0x11111100b muuten c = c1 & 0x00000011bC : ssä ja C++ : ssa bittikenttää määritettäessä käytetään kaksoispistettä ( :) . Kaksoispistettä seuraa vakiolauseke , joka määrittää bittien määrän bittikentässä [1] . Esimerkki:
struct rgb { allekirjoittamaton r : 3 ; unsigned g : 3 ; allekirjoittamaton b : 3 ; };