Byti in floati in poravnave

Vse o programiranju na in za PC

Moderatorji: Kroko, tilz0R

Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 18:53

Spet ena preprostih stvari, ki mi je ukradla dva dneva (in noči).
(Keil in Arm)

1. dan
Začelo se je pred mnogimi leti, ko so pisci Ethernet protokola določili, da je lahko header dolg 14 bytov. Za headerjem pride payload, ki pa seveda ni poravnan na 4. Če torej naredim tole:
float vrednost =*(float*)&payload[0];
dobim hard fault error.

2. dan
Ok, sedaj ko je problem poznan je rešitev enostavna. Ker gre za del kode, kjer optimizacijja ni pomembna sem preprosto napisal takole:
float vrednost = (float)(payload[0] + (payload[1]<<8) + (payload[2] <<16) + (payload[3]<<24));
potem pa sem še cel dan ugotavljal, zakaj dobim napačno vrednost

Vzrok sem našel. Me pa zanima, kaj si ostali mislite, da je bil problem?
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 2842
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 477 krat
Prejel zahvalo: 928 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 166

Re: Byti in floati in poravnave

OdgovorNapisal/-a mujo » 08 Mar 2017, 19:00

Pravilo tankega konca/pravilo debelega konca.
Nisem si jaz zmislil prevodov (islovar).
mujo
 
Prispevkov: 493
Pridružen: 21 Jan 2015, 10:50
Kraj: MB
Zahvalil se je: 0 krat
Prejel zahvalo: 78 krat
Uporabnika povabil: VolkD
Število neizkoriščenih povabil: 10

Re: Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 19:04

Ne ni bil to problem. Vrstni red je bil pravilen.
Sem pa zgornji post napisal na pamet tako da možno, da sem v postu naredil napako.

PS
Hvala za slovenski izraz. Tega nisem vedel.
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 2842
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 477 krat
Prejel zahvalo: 928 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 166

Re: Byti in floati in poravnave

OdgovorNapisal/-a TilenS » 08 Mar 2017, 19:45

Izpiše ti samo int v "float" obliki in ne IEE754.

Jaz za te byte pakirane IEE754 vrednosti ponavadi uporabim kar union:
Koda: Izberi vse
union {
  float f;
  uchar b[4];
} u;
u.b[3] = b0;
u.b[2] = b1;
u.b[1] = b2;
u.b[0] = b3;
return u.f;

Moraš pa pazit na endianness.
TilenS
 
Prispevkov: 226
Pridružen: 05 Feb 2015, 00:40
Zahvalil se je: 0 krat
Prejel zahvalo: 33 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 6

Re: Byti in floati in poravnave

OdgovorNapisal/-a Kroko » 08 Mar 2017, 20:20

Epilog:
Po IEE754 je 24000.0f enako 0x46BB8000
V Keil pa je 24000.0f enako 0x00005DC0

"Floating point representation" je tudi ena takih stvari, ker vsi takoj pomislimo na IEE754, resnica je je lahko drugačna.

Takole imam sedaj in deluje pravilno:
uint8_t tmp[4] = {payload[0], payload[1], payload[2], payload[3]};
float vrednost = *(float*)tmp;
http://www.planet-cnc.comKroko was here!
Uporabniški avatar
Kroko
 
Prispevkov: 2842
Pridružen: 14 Jan 2015, 12:12
Kraj: Ljubljana
Zahvalil se je: 477 krat
Prejel zahvalo: 928 krat
Uporabnika povabil: Vrtni palček
Število neizkoriščenih povabil: 166

Re: Byti in floati in poravnave

OdgovorNapisal/-a tilz0R » 09 Mar 2017, 13:01

Kroko je napisal/-a:Spet ena preprostih stvari, ki mi je ukradla dva dneva (in noči).
(Keil in Arm)

1. dan
Začelo se je pred mnogimi leti, ko so pisci Ethernet protokola določili, da je lahko header dolg 14 bytov. Za headerjem pride payload, ki pa seveda ni poravnan na 4. Če torej naredim tole:
float vrednost =*(float*)&payload[0];
dobim hard fault error.

2. dan
Ok, sedaj ko je problem poznan je rešitev enostavna. Ker gre za del kode, kjer optimizacijja ni pomembna sem preprosto napisal takole:
float vrednost = (float)(payload[0] + (payload[1]<<8) + (payload[2] <<16) + (payload[3]<<24));
potem pa sem še cel dan ugotavljal, zakaj dobim napačno vrednost

Vzrok sem našel. Me pa zanima, kaj si ostali mislite, da je bil problem?


1. Hardfault dobiš samo na CPU-ju, kjer unaligned access ni dovoljen (Če imaš Cortex-M, potem je CM0 je takšen, CM0+ že dovoli, ostali tudi dovolijo).
2. Float si pa narobe dobil ker pač to ni isto kot integer, da so biti linearno postavljeni in jih samo premikaš. Tukaj je potrebno paziti tudi na endianess. Tvoja koda nikakor ni portabilna.
"Words come easy, when they're true!"
Robbie Williams, Gary Barlow
Moj nickname je tilz[NULA]R.
Uporabniški avatar
tilz0R
 
Prispevkov: 929
Pridružen: 18 Jan 2015, 00:12
Kraj: Črnomelj
Zahvalil se je: 120 krat
Prejel zahvalo: 218 krat
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 224

Re: Byti in floati in poravnave

OdgovorNapisal/-a zanka » 09 Mar 2017, 13:19

Prenosljivost kode je trd oreh in zelo težko je narediti, da bo en program delal vsepovsod. Že klic ene sistemske funkcije (npr. operacijskega sistema), uporaba nekih knjižnic ali uporaba asm v samem programu lahko prenosljivost konča.
Uporabniški avatar
zanka
 
Prispevkov: 535
Pridružen: 17 Mar 2016, 01:16
Kraj: Krško
Zahvalil se je: 35 krat
Prejel zahvalo: 69 krat
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 12


Vrni se na Programski jeziki

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 1 gost

cron