ceckovy kviz

xPablo Pablo na xpablo.cz
Úterý Září 5 16:42:06 CEST 2023


Tak to ja pujdu asi trochu proti proudu.
Dlouhou dobu jsem se branil Ccku a zpetne to vyhodnocuju jako obrovskou 
chybu. Veci, ktere popisujete jsou dane spis neznalosti, nez chybou 
jazyka. Pokud jste psal pro Arduino, tak jste nejspis pouzil C++ a ne C. 
Kompilator hlasi spoustu chyb, ale Arduino IDE ma vypnute varovani, 
takze o nich nevite. Napriklad na ten (A=B) upozorni urcite. Datovy typ 
char neni v jazyce specifikovan, takze je implementacne zavisle, jestli 
je signed, nebo unsigned, ale pri porovnavani opet kompilator dokaze 
vypsat varovani, ze porovnavate znamenkovy typ s neznamenkovym. Pokud si 
zapnete, ze se varovani maji brat jako chyby, tak to prehlednout ani 
nemuzete. C++ je navic v porovnavani podstatne striktnejsi, nez 
"obycejne" Ccko, ale pokud mu reknete C-stylem pretypovani, tak 
kompilator nema co kontrolovat. Dalsi vec pak je, ze muzete pouzit 
lintery, ktere maji opravdove vyvojove prostredi primo v sobe, nebo se 
daji doplnit jako zasuvne moduly. Napr. cppcheck ve VSC, nebo clang-tidy 
v Clion - osobne povazuji clang-tidy za podstatne lepsi, nez cppcheck - 
dokaze totiz napriklad upozornit na to, ze se nejaka metoda da udelat 
const, nebo doporuci pouziti iteratoru kde to jde namisto "hloupeho" 
for... indexovani.
Pro me je pouziti C++ v mikrokontrolerech fakt dost podstatny skok v 
efektivite programovani. Vzdycky rikam: Pokud chcete videt vyhody C++ a 
objektoveho programovani, tak si vezmete NTC termistor, DS18B20 a 433MHz 
senzor teploty a zkuste napsat pro tyhle 3 cidla program, ktery bude 
vypisovat namerene teploty na seriovy port, pricemz nevite, kolik bude 
kterych cidel pripojenych. A az to budete mit hotove, tak zkuste ten kod 
rizsirit o pripojeni nejakeho teplotni cidla pres I2C, nebo treba nejaky 
IP teplomer. Na tomhle primitivnim prikladu se da ukazat pouziti 
objektoveho programovani, dedicnost, sablonovani (template) C++. A muze 
to fungovat i na beznem "nano" Arduinu (alespon do te doby, nez zacnete 
pouzivat prilis vyskou abstrakci). A az to budete mit hotove, tak zmente 
procesor treba na STM32, nebo ESP32, nebo SAMD21...

Pavel Brychta

Dne 05. 09. 23 v 15:24 Martin Záruba napsal(a):
>
> Když vidím, s čím tu všichni bojujete, tak mám pocit, že jsem dělal 
> dobře, že jsem se bránil jazyku C v jakékoli podobě. Nakonec mě stejně 
> dostihl v podobě nutnosti udělat program pro Arduino.
>
> Uznávám, že zápis je velmi úsporný. Například
>
> i++;
>
> nenapíšete asi v žádném jiném jazyku úsporněji. Na druhou stranu.... 
> Použili jste někdy někdo zápis
>
> if (A=B) {};
>
> a přitom je syntakticky správně. Kompilátor pochopitelně nic nehlásí a 
> já nemohl pochopit, proč program nefunguje. Holt zvyk z Pascalu, že 
> tak je to dobře.
>
> Nebo třeba to, že typ char obsahuje znaménko a tudíž porovnání 
> nefunguje. Nebo že v řetězci nesmí být 0x00.
>
> V krátkém, jednoduchém programu je asi to, že můžete porovnat cokoli s 
> čímkoli (když víte jak) a konverzi typů většinou neřešíte, vlastnost, 
> která zkracuje zápis. Ale zásadně zvyšuje pravděpodobnost chyby. Já 
> vím, Pascal je užvaněný a begin-end asi je opravdu horší, než {}, ale 
> úžasné je, že pokud chcete přiřadit k sobě něco, co k sobě nepatří, 
> musíte to zcela jasně říct, jinak je to syntaktická chyba.
>
> Nechci vyvolat flame, ale co je na C tak úžasné? (Fakt mě to pouze 
> zajímá, protože na to nemohu přijít)
>
> Martin Záruba
> Dne 5.9.2023 v 10:51 Pavel Hudeček napsal(a):
>> Myslím, že je lepší mít program funkční proto, že vím co dělám, ale i 
>> přesto v něm zbytečně nevymejšlet koniny:-)
>> Jestli se má zobrazit řádek textu, tak nejspíš stejně bude potřeba, 
>> aby někdo měl čas si ho přečíst, takže není důvod šetřit nějaké 
>> nanosekundy. Tzn. dal bych tam normální funkci. A ať si s ní 
>> optimizér pak udělá co chce.
>>
>> PH
>>
>> Dne 05.09.2023 v 8:46 Jan Waclawek napsal(a):
>>> Je pravda, ze to makro je v tomto pripade nerozumne, a ta funkcia je
>>> rozumnejsie riesenie.
>>>
>>> (Na druhej strane, ta posadnutost pravovernych C++-karov tym const...
>>> zhodou okolnosti v tomto konkretnom programe ten retazec 
>>> konstruujem...)
>>>
>>> Ale neviem, ako by mi to malo dojst. Aj som to skusil, gcc s -Wall a
>>> -Wpedantic nic nevyhlasil. A ani nema dovod. Ale ano, zakryje to 
>>> problem.
>>>
>>> Ano, cely problem je v tom, ze strlen() ma navratovy typ unsigned
>>> (spominany size_t), a -strlen() je teda uplne rovnako unsigned (dost 
>>> dlho
>>> som hladal v C99 kde to presne je, ze vysledok vyrazu ma ten isty 
>>> typ ako
>>> su konvertovane typy operandov, lebo to nie je v kapitole 
>>> Expressions kde
>>> by som to cakal, ale v kapitole 6.3.1.8 Usual arithmetic conversions).
>>> Inaksie povedane, ak je retazec dlhy povedzme 3, tak -strlen je u
>>> 32-bitoveho mcu 0xFFFFFFFD.
>>>
>>> Cize v makre to ((xx) < 0) je vzdy false a optimalizator to true vetvu
>>> vyhodi.
>>>
>>> Funkcia to zachrani tym, ze pri volani sa ta unsigned value 
>>> skonvertuje na
>>> signed. To je sice, prisne vzate, implementation defined, ale u twos
>>> complement (co je defacto standard a od C23 bude povinne) to dopadne 
>>> dobre
>>> :-).
>>>
>>> A teraz, co je lepsie? Mat zhodou okolnosti funkcny program nad 
>>> ktorym by
>>> ma ani nenapadlo sa zamysliet; alebo sa na nefunkcnom programe 
>>> naucit, ze
>>> size_t je unsigned a miesanie unsigned so signed zvykne dopadnut zle,
>>> takze sa tomu treba vyhybat?
>>>
>>> wek
>>>
>>>
>>> ----- Original Message ---------------
>>>
>>> To je jednoduché - vy pravověrní C-čkaři pouľíváte makra i tam, kde se
>>> to vůbec nehodí. Kdybyste pouľívali raději statické inline funkce jako
>>> static inline void LcdBXPrint (int xx, int yy, const char * s) {
>>>     LcdBPrint( (((xx) < 0) ? LCD_XMAX : 0) + (xx) * FONT_XSIZE, (yy) *
>>> FONT_YSIZE, s);
>>> }
>>> pak vám dojde, ľe argument xx nemůľe být unsigned (resp. size_t), pokud
>>> má vyhodnocen jako záporný a problém zázračně zmizí.
>>>
>>> Mrazík
>>>
>>> On 03. 09. 23 23:00, Jan Waclawek wrote:
>>>> Mam funkciu
>>>>
>>>>     void LcdBPrint(uint32_t x, uint32_t y, char * s);
>>>>
>>>> ktora vypise retazec na LCD s rozmermi LCD_XMAX, LCD_YMAX na 
>>>> poziciu x, y
>>>> pixelov od laveho horneho rohu.
>>>>
>>>> Vypisuje to neproporcionalnym fontom s rozmermi znaku FONT_XSIZE,
>>>> FONT_YSIZE.
>>>>
>>>> Z nejakych dovodov chcem vypisovat retazce zarovnane jeden za 
>>>> druhym; ale
>>>> niekedy chcem vypisovat retazce pod seba zarovnane na pravy okraj. 
>>>> To prve
>>>> vedie na volania typu:
>>>>
>>>>     LcdBPrint(doteraz_napocitane_znaky_od_laveho_okraja * 
>>>> FONT_XSIZE, riadok
>>>> * FONT_YSIZE , retazec);
>>>>
>>>> a to druhe na
>>>>
>>>>     LcdBPrint(LCD_XMAX - strlen(retazec) * FONT_XSIZE, riadok * 
>>>> FONT_YSIZE,
>>>> retazec);
>>>>    Vravim si, takto je to dost neprehladne, a pritom sa tam to 
>>>> nasobenie furt
>>>> opakuje. A tiez, tie dve veci su navzajom dostatocne podobne. Tak 
>>>> co keby
>>>> ze si napisem makro, do ktoreho bud zadam kladne x, co znamena pocet
>>>> znakov od laveho okraja, alebo zaporne x, co znamena pocet znakov od
>>>> praveho okraja:
>>>>
>>>>     #define LcdBXPrint(xx, yy, s) LcdBPrint( (((xx) < 0) ? LCD_XMAX 
>>>> : 0) +
>>>> (xx) * FONT_XSIZE, (yy) * FONT_YSIZE, s)
>>>>
>>>> Ked pisem zlava, tak mam
>>>>
>>>>     LcdBXPrint(doteraz_napocitane_znaky_od_laveho_okraja, riadok, 
>>>> retazec);
>>>>
>>>> co je pekne, prehladne, a funguje. Ale ked pisem zlava, tak
>>>>
>>>>     LcdBXPrint(-sizeof(retazec), riadok, retazec);
>>>>
>>>> nefunguje.
>>>>
>>>> Preco?
>> _______________________________________________
>> 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 bywww.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list


-- 
Pavel Brychta
http://www.xPablo.cz

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


Další informace o konferenci Hw-list