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

Re:Je jazyk C skutočne ťažký?
« Odpověď #75 kdy: 03. 06. 2025, 17:20:40 »
Já bych tomu třeba říkal polovičatost.
Zbrane nebo obsluhy? :)

Ale skutečnost, že nechává signed jako nedefinované mi přijde polovičaté. To máš stejné, jako kdyby byla nedefinovaná třeba konstrukce for jenom kůli tomu, že nějaký obskurní procesor nemá loopy. To není neznalost. To je jednoznačně  chyba na straně C. Nemá to zkoušet vůbec rozlišovat signed a unsigned, a pak bych to bral. Takhle říká, že si to bere na starost, a přitom kecá.

Jeden z důvodů, co jsem slyšel, je možnost více optimalizovat. Kompilátor může například předpokládat, že když k intu přičtete kladnou konstantu, tak výsledek bude vždy větší, než původní hodnota.


Re:Je jazyk C skutočne ťažký?
« Odpověď #76 kdy: 03. 06. 2025, 17:53:50 »
Ja sa z toho C asi snáď zbláznim :)

Wasper

  • ***
  • 205
    • Zobrazit profil
    • E-mail
Re:Je jazyk C skutočne ťažký?
« Odpověď #77 kdy: 03. 06. 2025, 18:28:41 »
nedefinovaná třeba konstrukce for jenom kůli tomu, že nějaký obskurní procesor nemá loopy.
Tak zrovna porovnávat požadavek na konkrétní, byť naprosto majoritně nejrozšířenější, reprezentaci intů s požadavkem na Turing-kompletnost mi nepřijde jako moc vhodný argument.

Prostě to, že je chování nedefinované znamená, že se danou funkcni nemá používat, je to mrzuté (ale to jsem si už postěžoval na začátku) ale nic, co se nedá řešit knihovnou/makrem/...
Podstatné je, aby toho platform-závislého kódu nebyla většina, a tomu céčko IMHO vyhovuje (alespoň v rámci toho, co mám doma, i386, x86_64, arm, risc-v, atmel). A aby programátor nebyl čuně a neměl ty ifdefy rozházené po celém projektu, což ... radši budu potichu, i když většinou se to vyřeší během "ještě to dám na malinu"  :D

Re:Je jazyk C skutočne ťažký?
« Odpověď #78 kdy: 03. 06. 2025, 21:19:44 »
Jenom takova technicka - k cemu je v C potreba operace posunu na signovane datove typy?

BoneFlute

  • *****
  • 2 043
    • Zobrazit profil
Re:Je jazyk C skutočne ťažký?
« Odpověď #79 kdy: 03. 06. 2025, 21:31:27 »
nedefinovaná třeba konstrukce for jenom kůli tomu, že nějaký obskurní procesor nemá loopy.
Tak zrovna porovnávat požadavek na konkrétní, byť naprosto majoritně nejrozšířenější, reprezentaci intů s požadavkem na Turing-kompletnost mi nepřijde jako moc vhodný argument.

Prostě to, že je chování nedefinované znamená, že se danou funkcni nemá používat, je to mrzuté (ale to jsem si už postěžoval na začátku) ale nic, co se nedá řešit knihovnou/makrem/...

V kontextu toho na co jsem reagoval, netvrdím tady, že je C k ničemu. Já tvrdím, že je to polovičaté, jako oponenturu tvrzení, že je to chyba programátora že si to má programátor nastudovat.


BoneFlute

  • *****
  • 2 043
    • Zobrazit profil
Re:Je jazyk C skutočne ťažký?
« Odpověď #80 kdy: 03. 06. 2025, 22:22:58 »
Já bych tomu třeba říkal polovičatost.
Zbrane nebo obsluhy? :)

Ale skutečnost, že nechává signed jako nedefinované mi přijde polovičaté. To máš stejné, jako kdyby byla nedefinovaná třeba konstrukce for jenom kůli tomu, že nějaký obskurní procesor nemá loopy. To není neznalost. To je jednoznačně  chyba na straně C. Nemá to zkoušet vůbec rozlišovat signed a unsigned, a pak bych to bral. Takhle říká, že si to bere na starost, a přitom kecá.

Jeden z důvodů, co jsem slyšel, je možnost více optimalizovat. Kompilátor může například předpokládat, že když k intu přičtete kladnou konstantu, tak výsledek bude vždy větší, než původní hodnota.

Za cenu toho, že to občas bude počítat blbosti. Optimalizace jak stehno.

Wasper

  • ***
  • 205
    • Zobrazit profil
    • E-mail
Re:Je jazyk C skutočne ťažký?
« Odpověď #81 kdy: 04. 06. 2025, 02:24:58 »
V kontextu toho na co jsem reagoval, netvrdím tady, že je C k ničemu. Já tvrdím, že je to polovičaté, jako oponenturu tvrzení, že je to chyba programátora že si to má programátor nastudovat.
Ale jó, takhle to beru.
Každá z těch našich lopat má nějaké vady na kráse. I když v případě Céčka a (když už jsme u těch rantů) než na tohle, tak bych spíš nadával na existenci strncpy() a (standardní) neexistenci strlcpy() https://man.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3 , což mě vadí přes víc než čtvrt století.

Re:Je jazyk C skutočne ťažký?
« Odpověď #82 kdy: 04. 06. 2025, 06:27:26 »
Já bych tomu třeba říkal polovičatost.
Zbrane nebo obsluhy? :)

Ale skutečnost, že nechává signed jako nedefinované mi přijde polovičaté. To máš stejné, jako kdyby byla nedefinovaná třeba konstrukce for jenom kůli tomu, že nějaký obskurní procesor nemá loopy. To není neznalost. To je jednoznačně  chyba na straně C. Nemá to zkoušet vůbec rozlišovat signed a unsigned, a pak bych to bral. Takhle říká, že si to bere na starost, a přitom kecá.

Jeden z důvodů, co jsem slyšel, je možnost více optimalizovat. Kompilátor může například předpokládat, že když k intu přičtete kladnou konstantu, tak výsledek bude vždy větší, než původní hodnota.

Za cenu toho, že to občas bude počítat blbosti. Optimalizace jak stehno.
Já bych se toho samotného nedefinovaného chování zastal. Ono to umožňuje i řešit přetečení jako tvrdou chybu (-ftrapv). Přiznejme si, že při přetečení i v jiných jazycích obvykle nechceme wrap, ale je to něco co jsme neplánovali.

Ale tady zase nastupuje ta zmiňovaná polovičatost. Protože C nám nedává funkce pro ty výjimečné případy, kdy potřebujeme ten wrap.

Re:Je jazyk C skutočne ťažký?
« Odpověď #83 kdy: 04. 06. 2025, 10:23:43 »
Jenom takova technicka - k cemu je v C potreba operace posunu na signovane datove typy?

Taky jsem se chtěl zeptat. S tím se zase tak často člověk nesetká. S unsigned posuny ano, ale se signed?

Re:Je jazyk C skutočne ťažký?
« Odpověď #84 kdy: 04. 06. 2025, 10:41:05 »
Jenom takova technicka - k cemu je v C potreba operace posunu na signovane datove typy?

Taky jsem se chtěl zeptat. S tím se zase tak často člověk nesetká. S unsigned posuny ano, ale se signed?
Arithmetic right shift se dá použít na rychlé dělení konstantami 2, 4, 8, 16... signed čísel. I na současných CPU je integer dělení velmi drahá operace v porovnání s bit shiftem. Nelze přitom použít operátor dělení konstantou a doufat, že to překladač optimalizuje, protože integer dělení na signed integerech dává jiné výsledky než bitový posun. Výsledek operace (-1 / 2) je 0 a výsledek operace (-1 >> 1) je -1. Pokud se překladač rozhodne vygenerovat z operace dělení konstantou bitový posun, musí generovat extra kód, který tohle handluje.

Takže když chci extra rychlý kód pro dělení signed integerů konstantou a jsem smířen s tím, že to nedává identické výsledky jako operace dělení v C, je arithmetic right shift jediná varianta.

Re:Je jazyk C skutočne ťažký?
« Odpověď #85 kdy: 04. 06. 2025, 10:52:52 »
Jenom takova technicka - k cemu je v C potreba operace posunu na signovane datove typy?

Taky jsem se chtěl zeptat. S tím se zase tak často člověk nesetká. S unsigned posuny ano, ale se signed?
Arithmetic right shift se dá použít na rychlé dělení konstantami 2, 4, 8, 16... signed čísel. I na současných CPU je integer dělení velmi drahá operace v porovnání s bit shiftem. Nelze přitom použít operátor dělení konstantou a doufat, že to překladač optimalizuje, protože integer dělení na signed integerech dává jiné výsledky než bitový posun. Výsledek operace (-1 / 2) je 0 a výsledek operace (-1 >> 1) je -1. Pokud se překladač rozhodne vygenerovat z operace dělení konstantou bitový posun, musí generovat extra kód, který tohle handluje.

Takže když chci extra rychlý kód pro dělení signed integerů konstantou a jsem smířen s tím, že to nedává identické výsledky jako operace dělení v C, je arithmetic right shift jediná varianta.

jj já vím, co ta operace dělá. ale právě kvůli té problematické -1 (tedy samé jedničky v registru) to je IMHO vždycky způsob, jak se skutečně střelit do nohy. Vlastně právě i kvůli tomu, když píšu testy na kód se signed hodnotami, tak tam vždycky vrážím právě i -1, co to udělá.

docela bych řekl, že kdo toto potřebuje v praxi, tak prakticky vždycky by to měla být unsigned hodnota. Nějaký průchod polem dělením intervalu atd. - nezáporné indexy atd. Akorát unsigned je dlouhý slovo, tak jsme líní to psát...

Re:Je jazyk C skutočne ťažký?
« Odpověď #86 kdy: 04. 06. 2025, 10:57:58 »
jj já vím, co ta operace dělá. ale právě kvůli té problematické -1 (tedy samé jedničky v registru) to je IMHO vždycky způsob, jak se skutečně střelit do nohy. Vlastně právě i kvůli tomu, když píšu testy na kód se signed hodnotami, tak tam vždycky vrážím právě i -1, co to udělá.

docela bych řekl, že kdo toto potřebuje v praxi, tak prakticky vždycky by to měla být unsigned hodnota. Nějaký průchod polem dělením intervalu atd. - nezáporné indexy atd. Akorát unsigned je dlouhý slovo, tak jsme líní to psát...
Praktický případ - neuronka kvantizovaná do integer aritmetiky. Tam je fakt jedno, jestli je nějaká váha 0 nebo -1 v integeru, protože je to rozdí 0.0 vs něco jako -0.000001, což je na úrovni kvantizační chyby a nemá to vliv na výslednou accuracy.

Re:Je jazyk C skutočne ťažký?
« Odpověď #87 kdy: 04. 06. 2025, 13:39:37 »
Signed shift je užitečný, když potřebuju obecný sign-extend = rozkopírovat sign bit.
Třeba mám 48bit signed int a potřebuju z toho udělat 64: SHL16, SAR16 a je to.

Re:Je jazyk C skutočne ťažký?
« Odpověď #88 kdy: 05. 06. 2025, 08:17:32 »
jj já vím, co ta operace dělá. ale právě kvůli té problematické -1 (tedy samé jedničky v registru) to je IMHO vždycky způsob, jak se skutečně střelit do nohy. Vlastně právě i kvůli tomu, když píšu testy na kód se signed hodnotami, tak tam vždycky vrážím právě i -1, co to udělá.

docela bych řekl, že kdo toto potřebuje v praxi, tak prakticky vždycky by to měla být unsigned hodnota. Nějaký průchod polem dělením intervalu atd. - nezáporné indexy atd. Akorát unsigned je dlouhý slovo, tak jsme líní to psát...
Praktický případ - neuronka kvantizovaná do integer aritmetiky. Tam je fakt jedno, jestli je nějaká váha 0 nebo -1 v integeru, protože je to rozdí 0.0 vs něco jako -0.000001, což je na úrovni kvantizační chyby a nemá to vliv na výslednou accuracy.

Pravda, v tom případě by se to dalo použít. Takže v podstatě výpočet toho skalárního součinu s FX hodnotami na začátku každého neuronu a potom vydělení (posun) na správné místo řádové tečky. Dobře to je pěkný případ (i když popravdě se na to FX nehodí, možná ale není někdy zbytí, než mít jen integer aritmetiku).

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #89 kdy: 05. 06. 2025, 12:16:51 »
Takže když chci extra rychlý kód pro dělení signed integerů konstantou a jsem smířen s tím, že to nedává identické výsledky jako operace dělení v C, je arithmetic right shift jediná varianta.

Není to jedinná varianta. Lze definovat makro a na platforme ktera nepodporuje signed aritmetic right shift se da jeho chovani simulovat.

Kód: [Vybrat]
#ifdef HAS_ARITHMETIC_SHIFT
// Check that option is set incorrectly
static_assert(-8 >> 1 == -4, "Signed arithmetic right shift not implemented.");
#define SARS(value, shift) ((value) >> (shift))
#else

BUD:
// pomoci marka - bez kontroly datovych typu
#define SARS(value, shift) (((value) < 0) ? ~(~(value) >> (shift)) : ((value) >> (shift)))

A NEBO:
// pomoci funkce - s kontrolou datovych typu
#define SARS(value, shift) arithmetic_right_shift((value), (shift))

int arithmetic_right_shift(int value, int shift);
#endif

Definice helper funkce arithmetic_right_shift():
Kód: [Vybrat]
int arithmetic_right_shift(int value, int shift)
{
return value < 0 ?
~(~value >> shift) :
(value >> shift);
}

Toto cele lze navic zakomponovat do build procesu a zautomatizovat:

Kód: [Vybrat]
// File: test_sars.c
#include <stdio.h>

int main()
{
    int num = -8;
    int shifted = num >> 1;
   
    return (shifted == -4) ? 0 : 1;
}

Tento program build process spusti na zacatku a nastavi nekde option, neco jako:
Kód: [Vybrat]
if ./test_sars; then
    echo "#define HAS_ARITHMETIC_SHIFT 1"
else
    echo "#define HAS_ARITHMETIC_SHIFT 0"
fi
« Poslední změna: 05. 06. 2025, 12:20:23 od vrit »