FULL-C: 64 bit: Porovnání verzí
(Založena nová stránka s textem „ Tato stránka popisuje programovací jazyk '''FULL-C''', který je dostupný na vybraných zařízeních SDS. Některá zařízení používají SDS-C,…“) |
|||
Řádek 13: | Řádek 13: | ||
− | + | __NOTOC__ | |
== Detaily == | == Detaily == | ||
Řádek 28: | Řádek 28: | ||
Tisknutí lze provádět pomocí sprintf/snprintf/printf. | Tisknutí lze provádět pomocí sprintf/snprintf/printf. | ||
− | + | Vždy musíte správně použít "u" nebo "d" podle znaménka (unsigned nebo signed), a současně vždy uvést modifikátor délky "ll" (64-bit). Tedy "%lld" pro tisk typu int64_t. | |
Takže: | Takže: | ||
Řádek 36: | Řádek 36: | ||
hodnota64 = 1234; | hodnota64 = 1234; | ||
− | printf("hodnota je % | + | printf("hodnota je %llu \n", hodnota64); |
nebo | nebo | ||
Řádek 44: | Řádek 44: | ||
hodnota64sig = -1234; | hodnota64sig = -1234; | ||
− | printf("hodnota je % | + | printf("hodnota je %lld \n", hodnota64sig); |
− | Všimněte si, že jsme použili buď % | + | Všimněte si, že jsme použili buď %lld nebo %llu, právě přesně podle toho, jestli je to int64_t nebo uint64_t. |
Ještě lze použít %x pro hexa výpis (ten vypíše všech 64bitů tak jak jsou fyzicky v paměti, tady se na znaménka nehraje, viz také poznámka dále). | Ještě lze použít %x pro hexa výpis (ten vypíše všech 64bitů tak jak jsou fyzicky v paměti, tady se na znaménka nehraje, viz také poznámka dále). | ||
Řádek 59: | Řádek 59: | ||
hodnota64 = 1234; | hodnota64 = 1234; | ||
− | printf("hodnota je % | + | printf("hodnota je %lld \n", (int64_t) hodnota64); // vytiskne 1234 |
Řádek 122: | Řádek 122: | ||
x *= 1000000000; | x *= 1000000000; | ||
− | printf("hodnota = % | + | printf("hodnota = %llu \n", x); // vytiskne číslo 1024000000000 což je delší než 32bitů, takže to '''funguje''' |
(pro info: v hexa tvaru to je: 0xEE6B280000). | (pro info: v hexa tvaru to je: 0xEE6B280000). | ||
Jak snadné. | Jak snadné. |
Aktuální verze z 17. 11. 2022, 17:34
Tato stránka popisuje programovací jazyk FULL-C, který je dostupný na vybraných zařízeních SDS. Některá zařízení používají SDS-C, pro který máme návody jinde na této WiKi.
FULL-C a podpora 64 bitových čísel
Nová verze FULL-C pracuje nejen s 32bit čísly (int, long, nebo menší), ale také s 64bit čísly.
Použití 64bit je nezbytné v řadě úkolů, např. počítadla impulsů, nebo při provádění výpočtů, kdy mezivýsledky jsou větší než co by se do 32bit čísel vlezlo.
64bit čísla lze také výhodně využít pro fixed-point aritmetiku, pokud nám nestačí přesnost typu float (32bit), který SDS nabízí.
Pozor, počítání s 64bit čísly je jemně (nezřetelně, ale přece) pomalejší než nativní použití 32bit čísel či floatu, ale to je nakonec jen nepodstatné upozornění. A samozřejmě zaberou 8 bajtů paměti, oproti 4 bajtům pro 32bit čísla. Ale to je jasné a to nakonec chceme.
Detaily
Deklarace je možná pouze pomocí uint64_t nebo int64_t :
// 64bit bez znaménka uint64_t u64; // 64bit se znaménkem int64_t i64;
Tisknutí lze provádět pomocí sprintf/snprintf/printf.
Vždy musíte správně použít "u" nebo "d" podle znaménka (unsigned nebo signed), a současně vždy uvést modifikátor délky "ll" (64-bit). Tedy "%lld" pro tisk typu int64_t.
Takže:
uint64_t hodnota64; hodnota64 = 1234; printf("hodnota je %llu \n", hodnota64);
nebo
int64_t hodnota64sig; hodnota64sig = -1234; printf("hodnota je %lld \n", hodnota64sig);
Všimněte si, že jsme použili buď %lld nebo %llu, právě přesně podle toho, jestli je to int64_t nebo uint64_t.
Ještě lze použít %x pro hexa výpis (ten vypíše všech 64bitů tak jak jsou fyzicky v paměti, tady se na znaménka nehraje, viz také poznámka dále).
Speciality
Lze použít přetypování, ale musíte tomu rozumět. Příklad tisku 64bit čísla, které je původně bez znaméka, jako číslo se znaménkem :
uint64_t hodnota64; hodnota64 = 1234; printf("hodnota je %lld \n", (int64_t) hodnota64); // vytiskne 1234
Ale:
uint64_t hodnota64; hodnota64 = 0x8FFFFFFF; printf("hodnota je %d \n", (int64_t) hodnota64); // vytiskne -1879048193
Takže pozor, ať nejste zmateni.
V 64bit je např. -1 (signed) fyzicky (v paměti kde proměnná leží) reprezentována jako 0xFFFFFFFFFFFFFFFF (unsigned) atd. viz následující tabulka:
skutečná binární hodnota | 32-bit signed | 32-bit unsigned | skutečná binární hodnota | 64-bit signed | 64-bit unsigned | (32-bit) | FC signed int | FC unsiged int | (64-bit) | FC int64_t | FC uint64_t | ----------------------------------+---------------+-----------------+------------------------------------------------------------------+---------------+--------------------+ 00000000000000000000000000000000 | 0 | 0 | 0000000000000000000000000000000000000000000000000000000000000000 | 0 | 0 | 00000000000000000000000000000001 | 1 | 1 | 0000000000000000000000000000000000000000000000000000000000000001 | 1 | 1 | 00000000000000001111111111111111 | 65535 | 65535 | 0000000000000000000000000000000000000000000000001111111111111111 | 65535 | 65535 | 01111111111111111111111111111111 | 2147483647 | 2147483647 | 0000000000000000000000000000000001111111111111111111111111111111 | 2147483647 | 2147483647 | 10000000000000000000000000000000 | -2147483648 | 2147483648 | 1111111111111111111111111111111110000000000000000000000000000000 | -2147483648 | 0xFFFFFFFF80000000 | 10000000000000000000000000000001 | -2147483647 | 2147483649 | 1111111111111111111111111111111110000000000000000000000000000001 | -2147483647 | 0xFFFFFFFF80000001 | 10000000000000001111111111111111 | -2147418113 | 2147549183 | 1111111111111111111111111111111110000000000000001111111111111111 | -2147418113 | 0xFFFFFFFF8000FFFF | 11111111111111111111111111111111 | -1 | 4294967295 | 1111111111111111111111111111111111111111111111111111111111111111 | -1 | 0xFFFFFFFFFFFFFFFF |
Zkuste si to sami (např. v nějaké vhodné Kalkulačce) a uvidíte sami.
Pozor na nastavování z 32bit do 64bit
Pozor na to, jak jsou v jednotlivých typech (32bit oproti 64bit) reprezentovány záporná čísla.
Příklad:
unsigned int hodnota32; hodnota32 = 0x8FFFFFFF // což také odpovídá tomuto: -1879048193 (signed) int64_t h64s; h64s = hodnota32; // a pozor - h64s je teď uloženo v paměti jako: ( 0xFFFFFFFF8FFFFFFF unsigned ) což odpovídá (-1879048193 signed).
Nenechte se zmást - je to správně. Nastudujte si to. Jde jen o to si uvědomit jak to vše funguje.
Proto kde můžete, používejte čistě a jen uint64_t a vyhnete se tomu (ale nebudete mít záporný rozsah, což často nevadí, a pak jste v klidu a nemusíte na toto myslet).
Samozřejmě pro if (pro podmínky) platí to samé co pro 32bit čísla - if porovnává dvě strany, např. if (a<b) { něco(); }; . Pokud se porovnávají dvě strany a obě jsou signed, výsledek a proces porovnání je také signed. Ale jakmile je jedno z nich (nebo obě strany) unsigned, pak se všechny strany nejprve převedou na unsigned, a pak se provede porovnání a výsledek je také unsigned. Toto je dle C standardu, a už se na tom spousta vývojářů spálilo, dejte si proto pozor.
Omezení při inicializaci 64bit čísla
V současné verzi FULL-C umí SDS jen 32bitové konstanty. To se v nové verzi upraví a bude umět i 64bit konstanty, ale teď je ještě neumí.
Řešení je snadné, použijte "výpočet" pro nastavení výchozí hodnoty (je-li třeba nějaká nenulová).
uint64_t x; x = 1024; // toto je zápis 32bit konstanty do uint64_t x *= 1000000000; printf("hodnota = %llu \n", x); // vytiskne číslo 1024000000000 což je delší než 32bitů, takže to funguje (pro info: v hexa tvaru to je: 0xEE6B280000).
Jak snadné.