Je jazyk C skutočne ťažký?

Re:Je jazyk C skutočne ťažký?
« Odpověď #105 kdy: 08. 06. 2025, 09:23:35 »
V každém případě moderní překladač důrazně upozorní, že je něco jinak, a je na vývojáři aby napsal kód bez warningu. V Postgresu kód s warningem nemá šanci se dostat do upstreamu, a co jsem se jako vývojář naučil, že warning v Cčku není něco, nad čím by se dalo mávnout rukou.
Warning řeší jen malou část poblému. Warning uvidíš jen v případě, kdy překladač může ověřit, že k signed overflow dojde, tozn. jedná se o konstanty známe v době překladu. V případě, kdy se sčítají dva integery a jejich hodnota není známa v době překladu, tak nikde žádný warning nebude, ale pořád je to undefined behavior a pořád se může stát v runtime cokoliv. C překladač má "volnost" vygenerovat kód, který bude řešit signed oveflow v runtime např. vynulováním proměnné, nebo to může být overflow s wrap, nebo taky může klidně zavolat exit... Všechno je legální.


Re:Je jazyk C skutočne ťažký?
« Odpověď #106 kdy: 08. 06. 2025, 11:13:42 »
V každém případě moderní překladač důrazně upozorní, že je něco jinak, a je na vývojáři aby napsal kód bez warningu. V Postgresu kód s warningem nemá šanci se dostat do upstreamu, a co jsem se jako vývojář naučil, že warning v Cčku není něco, nad čím by se dalo mávnout rukou.
Warning řeší jen malou část poblému. Warning uvidíš jen v případě, kdy překladač může ověřit, že k signed overflow dojde, tozn. jedná se o konstanty známe v době překladu. V případě, kdy se sčítají dva integery a jejich hodnota není známa v době překladu, tak nikde žádný warning nebude, ale pořád je to undefined behavior a pořád se může stát v runtime cokoliv. C překladač má "volnost" vygenerovat kód, který bude řešit signed oveflow v runtime např. vynulováním proměnné, nebo to může být overflow s wrap, nebo taky může klidně zavolat exit... Všechno je legální.
Ano, např :
Kód: [Vybrat]
bool test(int i)
{
    return i+1 > i;
}
se zoptimalizuje na return true a to bez jakéhokoliv warningu.

xyz

  • ****
  • 282
    • Zobrazit profil
Re:Je jazyk C skutočne ťažký?
« Odpověď #107 kdy: 08. 06. 2025, 13:41:35 »
Ccko, narozdil od mnoha vsemoznych frikulinksych kravovin, po kterych za par let pes nestekne, dela presne to, co napises.
Jenže pokud nejsi velmi zkušený programátor, tak to znamená, že to velmi často dělá něco jiného, než chceš.

Nerozumim. Muzes dat nejaky priklad? Proc by mel delat _velmi casto_ neco jineho nez chci, kdyz ten jazyk je jednoduchy?
Tak schválně, co dělá tenhle nevinně vypadající kus kódu :
Kód: [Vybrat]
    for (int i = 0; i < 4; ++i)
        printf( "%d\n", i*1000000000 );

Odpověď zní že se může stát úplně cokoliv. :o V závislosti na platformě, překladači, náladě nosních démonů a fázi měsíce třeba :
- Vypíše to 4 čísla, které by člověk čekal. (obvykle debug, nebo staré překladače)
- Přeloží se to na nekonečnou smyčku. (novější překladače s optimalizacema)
- Vyoptimalizuje se to do pryč a vezme to ssebou půl programu. (pro tenhle konkrétní kód jsem to teda nepozoroval, ale je to legální a zažil jsem něco dost podobného)

Zkus tohle chování vysvětlit. Pokud možno _jednoduše_, když je C jednoduchý jazyk.  8)

V C jsem naposled programoval na VS, ale jestli tohle kompilátor přeloží na nekonečnou smyčku i s warningem, tak to jsou cunata.

A ten side effect je popsány ve specifikaci?

ByCzech

  • *****
  • 1 870
    • Zobrazit profil
    • E-mail
Re:Je jazyk C skutočne ťažký?
« Odpověď #108 kdy: 08. 06. 2025, 14:59:45 »
Konkrétně signed integer overflow zkoumají pod AO3 (vypnuli to pomocí -fwrapv) a rozdíly ve výkonu jsou zanedbatelné.

Ono je otázkou, co je dneska implementovatelné v překladači z pohledu zpětné kompatibility a očekávání uživatelů.

V každém případě moderní překladač důrazně upozorní, že je něco jinak, a je na vývojáři aby napsal kód bez warningu. V Postgresu kód s warningem nemá šanci se dostat do upstreamu, a co jsem se jako vývojář naučil, že warning v Cčku není něco, nad čím by se dalo mávnout rukou.

Od toho tu jsou switche jako třeba -std=xxx. Nečekám zcela plnou zpětnou kompatibilitu, pokud chci použít nové vlastnosti, právě proto, že nové vlastnosti odstraňují (měly by) spoustu starých nepěkností.

Re:Je jazyk C skutočne ťažký?
« Odpověď #109 kdy: 08. 06. 2025, 15:13:08 »
A ten side effect je popsány ve specifikaci?

Je to podle specifikace - kompilátor si může dělat, co chce, v případě přetečení signed intu. Nicméně některé kompilátory dovolují zvolit chování, co se má stát v případě přetečení (ale to už specifikace C nepožaduje, to je navíc, nepovinná vlastnost).


Re:Je jazyk C skutočne ťažký?
« Odpověď #110 kdy: 08. 06. 2025, 16:08:19 »
Jestli tady ještě OP čte, tak za mě pro učení C je ideální Arduino. Člověka potěší i ta rozblikaná LEDka. Také je to low level, a vyšší jazyky se tam nevejdou, takže C je rozumná volba. Rozblikaný kurzor v terminálu nemá takové kouzlo.
Poslat něco po sériové lince, přerušení, atd.
Pak se dá třeba na ESP napsat hloupý HTTP server.

Re:Je jazyk C skutočne ťažký?
« Odpověď #111 kdy: 08. 06. 2025, 16:55:11 »
V C jsem naposled programoval na VS, ale jestli tohle kompilátor přeloží na nekonečnou smyčku i s warningem, tak to jsou cunata.

A ten side effect je popsány ve specifikaci?
Tam je problém, že ten kus kódu nemá žádné správné chování.

Norma C říká, že když jako programátor dopustíš, aby ti kdekoliv v kódu přetekl int, tak dává od celého tvého programu ruce pryč.

Překladače se snaží obvykle udělat něco příčetného, ale ne vždycky se to dá.

Re:Je jazyk C skutočne ťažký?
« Odpověď #112 kdy: 08. 06. 2025, 19:04:45 »
Jestli tady ještě OP čte, tak za mě pro učení C je ideální Arduino. Člověka potěší i ta rozblikaná LEDka. Také je to low level, a vyšší jazyky se tam nevejdou, takže C je rozumná volba. Rozblikaný kurzor v terminálu nemá takové kouzlo.
Poslat něco po sériové lince, přerušení, atd.
Pak se dá třeba na ESP napsat hloupý HTTP server.

Nepíše sa pre Arduino v C++ náhodou?

Re:Je jazyk C skutočne ťažký?
« Odpověď #113 kdy: 08. 06. 2025, 23:47:28 »
Jestli tady ještě OP čte, tak za mě pro učení C je ideální Arduino. Člověka potěší i ta rozblikaná LEDka. Také je to low level, a vyšší jazyky se tam nevejdou, takže C je rozumná volba. Rozblikaný kurzor v terminálu nemá takové kouzlo.
Poslat něco po sériové lince, přerušení, atd.
Pak se dá třeba na ESP napsat hloupý HTTP server.

Nepíše sa pre Arduino v C++ náhodou?

hodinky, holinky... typickej arduinista

Re:Je jazyk C skutočne ťažký?
« Odpověď #114 kdy: 09. 06. 2025, 07:37:31 »
Jestli tady ještě OP čte, tak za mě pro učení C je ideální Arduino. Člověka potěší i ta rozblikaná LEDka. Také je to low level, a vyšší jazyky se tam nevejdou, takže C je rozumná volba. Rozblikaný kurzor v terminálu nemá takové kouzlo.
Poslat něco po sériové lince, přerušení, atd.
Pak se dá třeba na ESP napsat hloupý HTTP server.

Nepíše sa pre Arduino v C++ náhodou?

hodinky, holinky... typickej arduinista
Tak ono C++ podědilo většinu chuťovek z C. Některé se podařilo trochu učesat a jiným zase C++ umožnilo rozvinout svůj destruktivní potenciál. :)

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #115 kdy: 10. 06. 2025, 10:35:13 »
Není to jedinná varianta. Lze definovat makro a na platforme ktera nepodporuje signed aritmetic right shift se da jeho chovani simulovat.
Tak to jste me s tim test_sars pekne nahlodal. Mam ve sve helper knihovne tuto variantu
Kód: [Vybrat]
int asr(int x, int n)
{
    return (x >= 0) ? (x >> n) : ((x >> n) | (~((~0U) >> n)));
}
ktera je nezavisla na posuvu (arith/log), presne z toho duvodu, ze jsem nenasel elegantni zpusob, jak v compile time detekovat implementaci >>. Optimalizace v gcc i clang si s tim neporadi a konci to vzdy na sar + shr. Nastesti jsem to nikdy nepotreboval.

Ano, při kompile-timu to opravdu detekovat nelze. Proto jsem přidal extra krok do buildovacího procesu - nejdříve se spustí testovací program, ten zjístí jak to daný překladač na oné architektuře má, a následně se na základě výsledku spustí buď optimalizovaný, nebo konzervativní překlad. Je to krok navíc v buildovacím procesu, ale umožňuje přeložit optimalizovaný kód - to jenom že Linuxák říkal, že když chci optimalizovaný kód, tak jiná cesta než spolehnout se na undefined behaviour není. Toto řešení má obojí. Kde to jde, tam je optimalizované, a kde to nejde, tak používá vlastní defined-behaviour implementaci.

Re:Je jazyk C skutočne ťažký?
« Odpověď #116 kdy: 10. 06. 2025, 12:20:18 »
Ano, při kompile-timu to opravdu detekovat nelze. Proto jsem přidal extra krok do buildovacího procesu - nejdříve se spustí testovací program, ten zjístí jak to daný překladač na oné architektuře má, a následně se na základě výsledku spustí buď optimalizovaný, nebo konzervativní překlad. Je to krok navíc v buildovacím procesu, ale umožňuje přeložit optimalizovaný kód - to jenom že Linuxák říkal, že když chci optimalizovaný kód, tak jiná cesta než spolehnout se na undefined behaviour není. Toto řešení má obojí. Kde to jde, tam je optimalizované, a kde to nejde, tak používá vlastní defined-behaviour implementaci.
Děkuji, to je hezká ukázka, jak je C prakticky velmi špatně použitelné. Abych dokázal použít operátor >> v C správně, tak musím:

  • Vědět, že je operátor >> implementation defined (většina lidí to neví a předpokládá, že se jedná o aritmetický shift).
  • Implementovat testovací program, který mi na dané platformě zjistí, jak se věci mají.
  • Implementovat vlastní operátor aritmetic right shift.
  • Při buidu spustit testovací program.
  • Podle výsledku testovacího programu udělat conditional compile.
  • Měl bych mít testy na obě varianty.
A to vše jen proto, že si C táhne v dnešní době naprosto nerelevantní dědictví, kdy nechce definovat operátor >> na signed integeru jako aritmetický shift. Nemá to žádný praktický smysl, protože aktuálně neexistuje relevantní CPU, které by nebyla instrukce pro aritmetický shift.

Re:Je jazyk C skutočne ťažký?
« Odpověď #117 kdy: 10. 06. 2025, 12:50:45 »
Vědět, že je operátor >> implementation defined (většina lidí to neví a předpokládá, že se jedná o aritmetický shift).

Pak by si asi měli přečíst dokumentaci. Stejně tak by někdo mohl říct, že v Rustu většina lidí neví, že chování + závisí na tom, jestli kompilujete Debug nebo Release. Nebo v C#, že se chování ToUpper a ToLower řídí aktuálním locale a někdy můžete dostat fakt nečekané výsledky. Nebo v Gleamu, dělení 0 vrací 0, není to chyba. A takových situací jsou hromady ať už jste v Rustu, C, C++, Go nebo F#. Je lepší nepředpokládat a přečíst si dokumentaci.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #118 kdy: 10. 06. 2025, 12:55:23 »
A to vše jen proto, že si C táhne v dnešní době naprosto nerelevantní dědictví, kdy nechce definovat operátor >> na signed integeru jako aritmetický shift. Nemá to žádný praktický smysl, protože aktuálně neexistuje relevantní CPU, které by nebyla instrukce pro aritmetický shift.

Tak kdyby C neměl jiné výhody, tak budiž. On je ale má a i přes toto všechno má cenu ho zvolit. Mimo jiné jakmile toto jednou vyřeším, tak mám vyřešeno jednou pro vždy, takže mě to už při dalším vývoji neobtěžuje.

Navíc se to dá řešit i jinak, ale už by to nebyl optimalizovaný kód. Byl by tam nějaky kompromis pohodlí vývojáře vs. výkoon (jak to koneckonců ostatní jazyky automaticky mají)

Navíc z mé praxe - nikdy jsem na to nenarazil, je to vyumělkovaný příklad. A hodnotit celé C jen na základě tady této jedné pro tebe neštastné věci je prostě biased.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #119 kdy: 10. 06. 2025, 12:57:54 »
Vědět, že je operátor >> implementation defined (většina lidí to neví a předpokládá, že se jedná o aritmetický shift).

Pak by si asi měli přečíst dokumentaci. Stejně tak by někdo mohl říct, že v Rustu většina lidí neví, že chování + závisí na tom, jestli kompilujete Debug nebo Release. Nebo v C#, že se chování ToUpper a ToLower řídí aktuálním locale a někdy můžete dostat fakt nečekané výsledky. Nebo v Gleamu, dělení 0 vrací 0, není to chyba. A takových situací jsou hromady ať už jste v Rustu, C, C++, Go nebo F#. Je lepší nepředpokládat a přečíst si dokumentaci.

Přesně tak. Znalost jazyka je nutná pro každý jazyk. A řeči typu "jazyk neděla co chci" = jen lenost si ho nastudovat. Každý jazyk se musí nastudovat, i ty moderní. Jestli to je někomu bližší, a snažší uchopit, tak budiž, ale ve výsledku je potřeba to nastudovat a tomu se člověk nevyhne ani v tom Rustu, ani C#. Každý jazyk má svá specifika a toto jsou dobré příklady že i v jiných jazycích se lze lehce střelit do nohy.