[C++] Bitprogramming probleem

Pagina: 1
Acties:

  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
Tijdens het ontwikkelen van een nieuw programma loop ik tegen het volgende probleem aan. Alle variabelen uit een classe moeten binair opgeslagen worden in 3 rijen. In de onderstaande code heb ik het desbetreffende stuk code gekopieerd. In dit stuk heb ik de variabelen vervangen door binaire data welke de maximum waarde van de variabele representeert.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
union {
  WORD w[3];
  struct {
    unsigned nLTO  : 5;
    unsigned nSense: 1;
    unsigned nMin  : 6;
    unsigned nHour : 5;
    unsigned nMJD : 17;
    unsigned nFree : 3;
    unsigned nDum : 11;
  };
} w3Blocks;
CGroup *g = (CGroup*)aGroups[0];
w3Blocks.w[0] = w3Blocks.w[1] = w3Blocks.w[2] = 0;
w3Blocks.nLTO = 0x1F;
w3Blocks.nSense = 0x1;
w3Blocks.nMin = 0x3F;
w3Blocks.nHour = 0x1F;
w3Blocks.nMJD = 0x1FFFF;
w3Blocks.nFree = 0x7;
w3Blocks.nDum = 0x7FF;


Als ik na deze code de w3Blocks.w[0], w3Blocks.w[1] en w3Blocks.w[2] bekijk, hebben deze respectievelijk de waarden:
1111.1111.1111.1111
0000.0000.0000.0001
1111.1111.1111.1111

Dit begrijp ik niet. ik verwacht de waarden:
1111.1111.1111.1111
1111.1111.1111.1111
0000.0000.0001.1111

Ik heb iedere variabele op zich geprobeerd en daarmee heb ik ontdekt dat de nLTO, nSense, nMin en nHour wel goed werken (bovense rij en de laatste bit van de tweede), maar de nMJD sluit niet direct aan, maar laat eerst 15 bits leeg en begint daarna de bits in de word array te zetten. Het probleem is dat deze direct na de nHour moet verder gaan zonder lege bits.

Ik hoop dat het probleem duidelijk genoeg is.. Anders wil ik het best nog eens proberen uit te leggen.

Kan iemand mij hiermee helpen?

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Misschien een alignment probleem? Wat is de grootte van je w3Blocks union?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dit begrijp ik niet. ik verwacht de waarden:
1111.1111.1111.1111
1111.1111.1111.1111
0000.0000.0001.1111
moet die laatste rij ook niet 1111.1111.1111.1111 zijn? (je zet iig alle bits aan met je code)

Maar is sizeof (w3Blocks) wel gelijk aan 6? Controleer dat even

(anonymous structs zijn overigens niet ISO C++)

[ Voor 11% gewijzigd door .oisyn op 30-09-2003 15:27 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
.oisyn schreef op 30 september 2003 @ 15:26:
[...]


moet die laatste rij ook niet 1111.1111.1111.1111 zijn? (je zet iig alle bits aan met je code)

Maar is sizeof (w3Blocks) wel gelijk aan 6? Controleer dat even

(anonymous structs zijn overigens niet ISO C++)
laatste moet inderdaad ook allemaal 1 zijn. (bij mijn vorige test stond de laatste waarde op 0, waardoor wel die 0000.0000.0001.1111 eruit zou moeten komen.

sizeof (w3Blocks) geeft als resultaat 8.

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

En moet dat niet 6 zijn, volgens jou? ;) 3 words van 2 bytes is immers 6 bytes

antwoord: packing
zie ook [rml][ C] Probleem met bitjes[/rml]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Dit zit 'm in alignment ja, en in endianness. De hele union als geheel wordt gepad tot 8 bytes.

Dit kun je afhankelijk van je compiler afvangen met een pragma :)

Professionele website nodig?


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
Het lukt niet direct, maar ik denk dat ik hier genoeg informatie aan heb en verder moet komen. Alvast bedankt!

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Voor alle duideklijkheid: dit soort code is altijd non-portable, er is een behoorlijk arbitraire keus hoe je bitfields in een word stopt, los van eventuele endianness. Dat wil dus zeggen dat twee x86 compilers het anders kunnen doen. De reden hiervoor is dat de adressen van members i.h.a op moeten lopen, maar bitfields hebben geen adres en daar geldt die regel niet voor.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
ik heb ondertussen het andere topic ([C] Probleem met bitjes) helemaal doorgelezen en ben opzoek gegaan naar informatie over packing en #pragma pack(), maar waarschijnlijk zie ik wat over het hoofd. De union heeft namelijk nog steeds een grootte van 8 bytes..

Deze code heb ik nu:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "stdafx.h"
...
# pragma pack( push, packing )
# pragma pack( 1 )

...
void CRds04a::Encode(){
union { 
  WORD w[3]; 
  struct { 
    unsigned nLTO  : 5; 
    unsigned nSense: 1; 
    unsigned nMin  : 6; 
    unsigned nHour : 5; 
    unsigned nMJD : 17; 
    unsigned nFree : 3; 
    unsigned nDum : 11; 
  }; 
} w3Blocks; 
w3Blocks.w[0] = w3Blocks.w[1] = w3Blocks.w[2] = 0; 
w3Blocks.nLTO = 0x1F; 
w3Blocks.nSense = 0x1; 
w3Blocks.nMin = 0x3F; 
w3Blocks.nHour = 0x1F; 
w3Blocks.nMJD = 0x1FFFF; 
w3Blocks.nFree = 0x7; 
w3Blocks.nDum = 0x7FF;


nog steeds gaat het fout bij de nMJD. Wat mij wel opgevallen is, is dat als ik deze ipv 17, 15 bits groot maak, het verder wel goed gaat. Alleen is dat in het programma niet mogelijk omdat 17 bits vereist is..

Doe ik iets fout met packing en alignement, of zit de fout mogelijk toch ergens anders?

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarschijnlijk omdat nMJD over een doubleword boundary heen gaat. Met 15 bits stop je precies voor de grens, maar vanaf 16 ga je er overheen
Welke compiler gebruik je eigenlijk?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
die van ms visual c++ 6

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 00:19

Reptile209

- gers -

.oisyn schreef op 01 October 2003 @ 12:07:
Waarschijnlijk omdat nMJD over een doubleword boundary heen gaat. Met 15 bits stop je precies voor de grens, maar vanaf 16 ga je er overheen
Welke compiler gebruik je eigenlijk?
Ga je dan met hour niet net zo hard de mist in? Als ik 'm uitteken, gaat Hour ook sowieso over een grens heen:
code:
1
2
3
4
5
6
7
8
|       w[0]      |       w[1]      |       w[2]      |       w[-]      |
|76543210|76543210|76543210|76543210|76543210|76543210|76543210|76543210|

 |  nDum    || ||     nMJD        ||nHr ||nMin| ||LTO|
            nFree                             NSense

 |LTO|||nMin ||nHr ||     nMJD        || || nDum     |
   nSense                              nFree

Even twee keer gedaan, afhankelijk van de volgorde waarop de bitfields ook al weer worden toegewezen... Maar in alle gevallen lijken zowel nHour als nMJD over word-grenzen heen te gaan. Misschien dat je door wat te rommelen met dummy-align velden de boel alsnog recht kunt trekken?

Zo scherp als een voetbal!


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
hour gaat ook over de grens heen. dat klopt, maar om een of andere reden doet dat het wel goed. als ik alleen de hour een waarde geef, krijg ik eruit:
1111.0000.0000.0000
0000.0000.0000.0001
0000.0000.0000.0000

maar wat bedoel je met dummy-align velden?

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Reptile209 schreef op 01 oktober 2003 @ 12:24:
[...]

Ga je dan met hour niet net zo hard de mist in? Als ik 'm uitteken, gaat Hour ook sowieso over een grens heen:
een doubleword is 32 bits, niet 16 ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik heb het hier even getest met MSVC++ 7.1, en ik krijg sizeof (w3Blocks) met geen mogelijkheid op 6.

Ik denk dat je het dan maar bij die 3 words moet houden, en bijvoorbeeld functies moet maken zodat je de aparte bits kunt zetten

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • pinkwin|IA
  • Registratie: Juni 2003
  • Laatst online: 23-04-2004
ik heb er alsnog 15 bits van gemaakt en dan de twee overgebleven bits met de hand gezet (checken op grootte van nMJD en dat verminderen met 65536 voor de eerste bit en met 32768 voor de tweede bit. Dit lijkt goed te werken.
In ieder geval bedankt voor de moeite!!

Ik zeg maar zo, ik zeg maar nix. dan zeg ik al veel te veel.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Misschien is het toch makkelijker om dit soort bitops met de hand te schrijven. Dan krijg je dus
code:
1
2
3
4
5
6
7
8
9
10
11
void w3Blocks::setLTO( int i )
{
  // bits 15-11
  w[0] &= (0x07FF);
  w[0] |= i * 0x800;
} 
int w3Blocks::getLTO( ) const
{
  // bits 15-11
  return w[0]  / 0x0800;
}

De compiler zou toch dit soort code moeten maken, en zo heb je volledige controle. Als je over een word grens heenwil, dan gebruik je simpelweg w[i] en w[i+1]. Overigens is het netter om in zo'n geval unsigned char[]s te gebruiken, die zijn altijd packed.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1