Bitfield (C++)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 6. lokakuuta 2014 tarkistetusta versiosta . tarkastukset vaativat 48 muokkausta .

Bittikenttä ( eng.  bit field ) ohjelmoinnissa  - joukko bittejä , jotka on järjestetty peräkkäin muistiin , jonka arvoa prosessori ei pysty lukemaan laitteistototeutuksen erityispiirteiden vuoksi .

Tietoja laitteistototeutuksista

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 2
  1. Prosessori lukee muistista konesanan , joka on yhtä suuri kuin alkuperäinen arvo:
0011 0100 1010 11 10 01 00 0111 0100 1100 2
  1. Käsky asettaa bitit , and jotka eivät ole bittikentässä, arvoon 0. Tulos:
0000 0000 0000 00 10 01 00 0000 0000 0000 2
  1. Käsky siirtää bittikentän bittejä vasemmalta oikealle niin, että bittikentän vähiten merkitsevä bitti tulee konesanan vähiten merkitseväksi bitiksi . Tulos:shr
0000 0000 0000 0000 0000 0000 0000 1001 2

Jos muistista luettavan arvon osoitetta ei ole kohdistettu koneen sanarajaan , tarvitaan lisävaiheita:

Esimerkki. Päästää:

0011 0100 1010 1110 0100 011 1 0100 1100 2 0011 01 00 1010 1110 0100 0111 0100 1100 2
  1. Prosessori lukee muistista kaksi konesanaa, jotka sisältävät halutut bitit; arvot ovat samat kuin alkuperäiset:
0011 0100 1010 1110 0100 011 1 0100 1100 2 0011 01 00 1010 1110 0100 0111 0100 1100 2
  1. Kahden käskyn and avulla bittikenttään kuulumattomat bitit kirjoitetaan arvoilla 0. Tulos:
0000 0000 0000 0000 0000 000 1 0100 1100 2 0011 01 00 0000 0000 0000 0000 0000 0000 2
  1. Toisen konesanan bittejä siirretään käskyn avulla vasemmalta oikealle siten, että bittikentän vähiten merkitsevä bitti tulee konesanan vähiten merkitseväksi bitiksi . Käskyn avulla ensimmäisen konesanan bittejä siirretään oikealta vasemmalle siten, että vähiten merkitsevät bitit vapautuvat toisen konesanan biteille (seuraavaan vaiheeseen). Tulos:shr shl
0000 0000 0000 0000 0 101 0011 00 00 0000 2 0000 0000 0000 0000 0000 0000 00 00 1101 2
  1. Käskyn avulla kahden konesananor bitit "listyvät" päällekkäin. Tulos:
0000 0000 0000 0000 0 101 0011 0000 1101 2

Kuvatut lisävaiheet voidaan suorittaa:

Haittapuoli: ylimääräiset komennot hidastavat ohjelman suorittamista . Etu: bittikenttiä käytettäessä saavutetaan tihein tiedon pakkaus .

Tietoja kääntäjistä

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ä.

Sovellus

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ä.

Toiminnot monibittisillä kentillä

Olkoon yhdessä tavussa neljä bittikenttää:

Bittinumero 7 [*1] 6 5 neljä 3 2 yksi 0 [*2]
bittikenttä d c b a
  1. 7. bitti on merkittävin bitti.
  2. 0. bitti on vähiten merkitsevä bitti.

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 .

Yhden numeron kokoaminen bittikentistä

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 ) | a

Binääriluvun looginen siirtymä vastaa kertomista/jakamista kahden potenssin kerrannaisella: 2 1 =2, 2 2 =4, 2 3 =8 jne.

Bittikentän purkaminen

On kaksi tapaa saada luvun x jonkin bittikentän arvo v :

  • v = ( x & mask_1 ) >> offset;
  • v = ( x >> offset ) & mask_2.

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:

  1. laske "bittimaski" maski_1  - luku, jonka bittikenttää vastaavissa biteissä on yksiköitä ja jäljellä olevissa biteissä nollia;
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
  1. kerro "bittimaski" numerolla käyttämällä " bittiä AND " -toimintoa;
  2. suorittaa loogisen siirron oikealle offset - biteillä.
bittikenttä offset
a 0
b yksi
c 2
d neljä

Esimerkki arvon saamisesta bittikentästä c :

c = ( x & 00001100 b ) >> 2

Toisella menetelmällä:

  1. suorita looginen siirto oikealle;
  2. laske "bittimaski" maski_2  - luku, jossa ensimmäiset n vähiten merkitsevää numeroa on asetettu ykkösiin ja loput numerot ovat nollia; n  on bittikentän numeroiden lukumäärä;
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
  1. kerro "bitmaski" numerolla käyttämällä " bittiä AND " -toimintoa.

Esimerkki arvon saamisesta bittikentästä c :

c = ( x >> 2 ) & 00000011 b

Vähiten merkitsevää bittikenttää (kenttä a tässä esimerkissä) ei ole loogisesti siirretty nollalla bitillä. Esimerkki:
a = ( x & 00000001b ) >> 0
a = ( x >> 0 ) & 00000001b )

a = x & 00000001 b

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 )

d = x >> 4

Bittikentän korvaaminen

Bittikentän korvaamiseksi suoritetaan kolme toimintoa:

  1. lasketaan maski - luku, jonka bittikenttää vastaavilla biteillä on nollia;
  2. operaatio " bitti JA " kertoo luvun x maskilla; operaatio suorittaa nollien asettamisen maskia vastaaviin bitteihin;
  3. operaatiota " bitt mukaan lukien TAI " käytetään summaan tuloksena saatu tulo ja numero x siirretty bittikentän poikkeamaa vastaavalla bittimäärällä sanan alusta.

Esimerkki bittikentän d arvon korvaamisesta :

xuusi = ( x & 00001111 b ) | ( d << 4 )

Toiminnot yksibittisillä kentillä

On olemassa yksinkertaisempia tapoja työskennellä yhden bitin leveiden bittikenttien kanssa.

Bittikentät a ja b vievät kukin yhden bitin.

Tarkistetaan yhtä bittiä

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 )

Biittien asettaminen

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 _

Biittien poistaminen

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 b

Beat Switching

Bittien 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 _

Toiminnot allekirjoitetuilla kentillä kahden komplementin

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 .

Numeroiden kokoaminen ja korvaaminen

Jokainen termi (paitsi korkein), jotta se ei pilaa korkeampia bittejä, on kerrottava sopivan pituisella bitimaskeella. Erityisesti:

x = (d << 4) + ((c & 00000011b) << 2) + (b << 1) + a

Lukujen poimiminen

Lukujen 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 4

Huomio! 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 & 0x00000011b

Bittikenttäilmoitukset

C : 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 ; };

Katso myös

Muistiinpanot

  1. Ray Lishner. C++. Viite = C++ pähkinänkuoressa / Ch. toim. E. Strogonova. - Pietari. : Peter , 2003 . - S. 193. - 907 s. - 3500 kappaletta.  - ISBN 5-94723-928-0 , BBC 32.973-018.1ya22, UDC 681.3.06(03).