ceckovy kviz

Jan Waclawek konfera na efton.sk
Úterý Září 5 08:46:55 CEST 2023


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?
> 
> wek
> 



Další informace o konferenci Hw-list