Pretypovani ukazatele struktury na bajt
Josef Štengl
ok1ced na nagano.cz
Středa Únor 26 12:24:11 CET 2020
... a když jste to zvládl, tak si to cvičně zkuste na platformě bigendian (dopadne to stejně), a/nebo se sizeof(int) = 1
=> 16 bit a tváři se jako 32 bitový. Tam je to docela sranda. Pak ještě pro 64 bitová čísla, nezapomenout zkusit různé
překladače a optimalizace a nastavit překladač na různé normy C (c99 se chová trošku jinak).
Nebo se na to všechno vykašlat a používat důsledně stejné typy pro jednu operaci, pokud to nejde, důsledně přetypovávat a
nespoléhat se na přetečení. To pak funguje všude stejně. Tedy pokus nebudete používat uint8_t, protože to ne vždy existuje.
P.S.:
Nemyslím to vážně, uvádím to pro pobavení.
Dne 25. 02. 20 v 19:16 David Obdrzalek napsal(a):
> Díky za precizní vysvětlení.
> Tak jsem to nakonec vlastně domyslel v souladu s normou :-)))
>
> ----
> Hlavní chybu jsem myslím udělal v tom, že jsem nezpozoroval znaménkovost
> hexadecimální konstanty. Tu pak normou nedefinované chování shiftu při posouvání
> signed typu "přes rozsah" kvalitně využilo.
>
> Pokusy na konstantách se mi ale povedly, protože tu chybu odhalily. Kdybych místo
> 0xAD vzal něco < 0x80, tak by se moje přehlédnutí neprojevilo a já žil dál v
> nevědomosti...
>
> A uplně na závěr, když jsem se podíval, jaký kód se vygeneruje pro (špatně napsané)
> hdr.ident = c | d << 8 | ((uint32_t)e) << 16 | ((uint32_t)f) << 24;
> tak je to udělané tak, aby to nedefinované chování bylo za běhu stejné, jako když
> jsem tam fouknul konstanty, jejichž uložení zařídil kompilátor. To je krásný, že to
> je konzistentní :-)
>
>
> D.O.
>
>
> On 25 Feb 2020 at 17:49, Jan Waclawek wrote:
>>> tak se
>>> spoléhám na weka, že to vysvětlí :-)
>>
>> :-(
>>
>>> Nerozumím ale tomu, že 0xADDE přiřazeno do 32bit unsigned se roztáhne do 32bit
>>> unsigned bez znamínka (zde implicitně),
>>
>> 0xADDE je kladna konstanta >32767 ktora nie je reprezentovatelna v int
>> (t.j. v avr_gcc int16_t), takze jeho typ je unsigned int (avr_gcc:
>> uint16_t), vid dole.
>>
>>
>>> ale 0xAD se po posunutí o 8 doleva a pak
>>> přiřazení do 32bit unsigned (opět implicitně) roztáhne znamínkově.
>>
>> V skutocnosti tu nejde o konverziu, ale sa jedna o vedlajsi efekt
>> nedefinovaneho spravania, 0xAD ma implicitny typ int (t.j. v avr_gcc
>> int16_t), a 0xAD << 8 je 0xAD00= co je >32767 t.j. v int to nie je
>> reprezentovatelne,
>> gcc v tomto pripade moze urobit uplne cokolvek, aj prekvapenie; a aj to
>> obcas v mene optimalizacie robi, takze na to pozor.
>>
>> C99 6.5.7#4
>> The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
>> are filled with
>> zeros.
>> [...]
>> If E1 has a signed
>> type and nonnegative value, and E1 × 2^E2 is representable in the result
>> type, then that is
>> the resulting value; otherwise, the behavior is undefined.
>>
>>
>>
>>>> Ale to s tím hextem že je vždy znamínkový se mi nějak nezdá, měl jsem za to, že ten
>>>> postup je "když se vejde do int tak int, když ne, tak unsigned int, když ne, tak
>>>> long int atd.".
>>
>> Ano, pre hexadecimalnu konstantu to plati, pre decimalnu nie, ta je vzdy
>> znamienkova.
>> C99, 6.4.4.1#5, je tam na to tabulka.
>>
>> wek
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
Další informace o konferenci Hw-list