RE: přístup na byty v int C

Miroslav Draxal evik na volny.cz
Úterý Říjen 29 09:13:48 CET 2013


Dobrý den,

Tak konkrétně, vynechme načítání z eeprom, a dejme tomu, že do int potřebuji zapsat 0xAA a 0xBB aby výsledek byl 0xAABB. Jde o PIC, hitech kompiler. V asm jsou to 4 řádky, hitech si stím moc neporadí. Chci mu napovědět. Ale nějak nenapadá jak. 

 

From: hw-list-bounces na list.hw.cz [mailto:hw-list-bounces na list.hw.cz] On Behalf Of Josef Štengl
Sent: Tuesday, October 29, 2013 8:35 AM
To: HW-news
Subject: Re: přístup na byty v int C

 

Souhlasím, jen doplním.

Pokud převádíte číslo z jedné velikosti typu do jiné a to oběma směry včetně prohazování bytů (pro ten samý typ) zapomeňte
na na ukazatele a použijte bitové posuny:
  · ukazatele jsou závislé na endianitě (litte endian je sice dominantní leč ne jediný používaný)
  · přistupování ke stejné oblasti paměti pomocí ukazatelů na rozdílné velikosti je poněkud ošemetná věc, a je od C99
poněkud zpřísněna (viz  strict aliasing rule), see níže.
  · kompilátory většinou tyto konstrukce rozpoznávají a překládají optimalizovaně. Je pak docela deprimující, že se píšete
se čtyřmi delšími řádkami a vypadne z toho jedna instrukce :-)

Na union také pozapomeňte, protože u něj není zaručeno nic, kromě vnějšího chování (viz norma). Když už je vhodné ho
nasadit, tak se nasazuje se znalostí implementace daného kompilátoru. Další možný problém je při přístupu k proměnným
zarovnaným na hranici typu, ale to jsem nikdy neměl potřebu ověřovat.

A máte to vyřešeno :-).

Na ukazatele to chce vhodnější příklad.

ced




==================================================================

Zpřísněná pravidla pro přistupování k datům různými typy (pro C99 z C90)

– more precise aliasing rules via effective type

Info: Tuto problematiku lze vyhledat pod heslem strict aliasing rule.

Strict aliasing7) znamená, že kompilátor předpokládá, že dva objekty různého typu neodkazují na stejnou oblast paměti. Při
nedodržení tohoto pravidla mohou po překladu vzniknout obtížně odhalitelné chyby8).

Důvodem zavedení tohoto pravidla je aby autoři kompilátoru mohly bezpečně předpokládat, že změna jedné proměnné se
neprojeví změnou jiné. A naopak, kdy mají předpokládat, že proměnné mohou ukazovat na stejnou oblast paměti.

Například:

typedef struct
{
         uint16_t a;
         uint32_t b;
} sa_t;

typedef struct
{
         uint16_t a;
         uint32_t b;
} sb_t;

sa_t *a;
sb_t *b;

V tomto případě kompilátor předpokládá, že *a a *b neodkazují na stejnou oblast paměti ačkoliv formát struktur je shodný.

sa_t *c, *d;

int16_t i;
int16_t *p = &i;

Kompilátor předpokládá, že *c a *d resp i a *p mohou respektive odkazují na stejnou oblast paměti a nebude používat
příslušné optimalizace.

Nebo.

int16_t i;
void fce(int16_t *j, int16_t *k);

fce(&i, &i);

Pokud je funkce fce() volána tímto stylem (stejné typy parametrů, resp hodnota parametru), tak se předpokládá, žej a k
ukazují na stejnou oblast paměti.

Převedení a dereference neshodných ukazatelů obvykle znamená porušení tohoto pravidla. Striktní aliasing je předpokládán C
kompilátorem, kterýžto předpokládá, že dereference ukazatelů na objekty rozdílného typu nebudou odkazovat na shodnou
oblast paměti9)

Pravidla pro aliasing určují okolnosti za kterých objekt může mít alias10) jsou definovány v kapitole 6.5 bod 7 standardu C99.
Možné vytváření aliasů

Vytváření aliasů je možné jen pro objekt k němuž je přistupováno pouze výrazem odkazujícím do oblasti paměti (lvalue) v
těchto případech.

     Efektivní typ nebo kvalifikovaná verze typu je shodná nebo kompatibilní s efektivním typem objektu.

Prakticky to znamená, že typy jsou kompatibilní pokud nejsou rozdílné datové typy, modifikátory mohou být různé.

uint32_t var;
uint32_t* const       a = &var;
uint32_t* volatile    b = &var;


     Typ celých nebo přirozených čísel kompatibilní s typem (efektivní nebo s kvalifikovanou verzí) objektu.

int32_t*              c = (int32_t*)&var;
int32_t* const        d = (int32_t*)&var;
int32_t* volatile     e = (int32_t*)&var;
const int32_t* const  f = (int32_t*)&var;


     Jednotlivé členy agregovaného typu (stuct) a typu union splňující předchozí podmínky (včetně vnořených členů).

struct s
{
         int32_t j;
         int32_t i;
         union u
         {
                 uint32_t u;
                 double d;
         }
};

double *f = &s.u.d;


     typ char Datové typy char*, signed char*, nebo unsigned char* mohou ukazovat kamkoliv na platnou adresu paměti bez
omezení.

uint64_t long;
int8_t* malej = (int8_t *)&long;




Dne 29.10.2013 01:17, Radek Benedikt napsal(a):
> Miroslav Draxal píše v Po 28. 10. 2013 v 23:10 +0100:
>> Samozřejmě, tudy cesta vede. Mě vrtá spíš jak to udělat přes ukazatele.
>> Určitě to nějak jde. Abych se něco naučil. Míra
>
>>> Ještě jsem zapomněl přidat jak to dělám do teď. Ale moc se mi to
>>> nelíbí.**
>>> **
>>>
>>>                                Linear.Krok = eeprom_read
>>> (EEpromLinearKorekce);****
>>>
>>>                                Linear.Krok <<= 8;****
>>>
>>>                                Linear.Krok |= eeprom_read
>>> (EEpromLinearKorekce+1);****
>>>
>>> ** **
>>>
>>> Jak přistoupit přes ukazatele na int Linear.krok (byt1 ; byt2)?****
>
>       Slo by pretypovat pointer na Linear.krok na typ pointer na byte,
> protoze inkrement ukazatele je o delku typu, nikoliv o byte. Nicmene je
> to trochu drbani levou rukou za pravym uchem.
>       Ukazatele bych nechal na pokoji a napsal bych to nacteni na jeden
> radek, misto na tri.Usnadni se tim kompilatoru prace s optimalizaci.
> Tohle je zrovna dost bezna konstrukce a kompilatory ji obvykle umi.
> Nesmi v ni byt ale neco co zavisi na poradi cteni te korekce z EEprom.
> Pak se ale neda spolehnout ani na to rozepsani na tri
> radky.Optimalizatory pri agresivnim nastaveni umi sahnout i do takoveto
> konstrukce. Optimalizace pointrove aritmetiky v prekladaci uz obvykle
> tak slusna neni, je to spis o rucni optimalizaci. Jenze pri ni se do
> toho zacinaji michat strojove zavisle veci a je pak sranda ten zdrojak
> portovat jinam. Objevi se napr. problem little/big endian.
>       Navic na vyse popsane konstrukci je videt, ze v podstate prirazeni int
> do int muze byt zpracovavane na nekolik kroku a neni proto atomicke. Je
> to docela sranda pri preruseni, kdyz by se cela ta korekce jednou za cas
> doladovala a skocila napr. z  0x3FF na 0x400. To ale jen na okraj.
>
>       Radek (bendikt2hw.cz)
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
_______________________________________________
HW-list mailing list  -  sponsored by www.HW.cz
Hw-list na list.hw.cz
http://list.hw.cz/mailman/listinfo/hw-list



__________ Informace od ESET NOD32 Antivirus, verze databaze 8978 (20131028) __________

Tuto zpravu proveril ESET NOD32 Antivirus.

http://www.eset.cz



__________ Informace od ESET NOD32 Antivirus, verze databaze 8978 (20131028) __________

Tuto zpravu proveril ESET NOD32 Antivirus.

http://www.eset.cz

------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20131029/c60d7f41/attachment.htm>


Další informace o konferenci Hw-list