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

Re:Je jazyk C skutočne ťažký?
« Odpověď #30 kdy: 03. 06. 2025, 10:45:34 »
C zachovava pri rotaci znamenko protoze rotace je provadena na znamenkovem typu, dela tedy tzv. aritmeticky bit shift.
Ani náhodou. Right shift na signed integeru je v C implementation defined. Překladač to může přeložit jako arimetický, nebo jako logický shift. Výsledek bude samozřejmě úplně jiný. Ke zbytku toho, co jsi napsal, se nebudu vyjadřovat, je to stejně nesprávné jako tvoje tvrzení, že je to aritmetický bit shift.


Re:Je jazyk C skutočne ťažký?
« Odpověď #31 kdy: 03. 06. 2025, 10:48:11 »
Zkus si domácí úkol, když napíšu tohle, bude výsledek -1, nebo 2147483647, nebo ještě něco úplně jiného?
Kód: [Vybrat]
printf("%d\n", -1 >> 1);

Tohle je prasana. Nikdo kdo ma praxi v C by tohle nenapsal. Spravne je to
Kód: [Vybrat]
printf("%d\n", ((int)-1) >> 1);

nesmysl, obe dve verze jsou naprosto totozne protoze
Kód: [Vybrat]
-1 a
Kód: [Vybrat]
((int) -1) je jedno a uplne to same. V C je numericky literal by default typu int.

C zachovava pri rotaci znamenko protoze rotace je provadena na znamenkovem typu, dela tedy tzv. aritmeticky bit shift.

Pokud by clovek chtel klasicky bit shift musi naopak prevest hodnotu na unsigned integer kde se nepracuje se znamenkem - a provest rotaci na nem.

Kód: [Vybrat]
printf("%d\n", -1 >> 1);
printf("%u\n", ((unsigned)-1) >> 1);

A taky zkuseny C programator by nepouzil -1 ale bud konstantu z <limits.h> a nebo
Kód: [Vybrat]
~0, ponevadz
Kód: [Vybrat]
-1 dava same jednicky jen na architekturach kde jsou zaporna cisla implementovana pomoci dvojkoveho doplnku, coz nemusi byt vsude. Existuji architektury, ktere zaporna cisla implementuji jinak.

Kód: [Vybrat]
~0 funguje vzdy a vsude.

Takze C dela presne to co ma a jestli nekdo tvrdi neco jineho, je to pouze jeho neznalost.

Pravda. Spravne se to ma napsat.
Kód: [Vybrat]
printf("%u\n", ((uint16_t)-1) >> 1);

Re:Je jazyk C skutočne ťažký?
« Odpověď #32 kdy: 03. 06. 2025, 10:49:47 »
Nicméně u většiny ostatních jazyků to vlastně ani nevíte, protože žádnou specifikaci nemají.
Nechtěl jsem to vytahovat, ale v Rustu je to definované docela jasně :) https://doc.rust-lang.org/reference/expressions/operator-expr.html

Arithmetic right shift on signed integer types, logical right shift on unsigned integer types.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #33 kdy: 03. 06. 2025, 10:52:52 »
Ahoj, moja otázka je veľmi jednoduchá. Je jazyk C skutočne ťažký alebo to je iba môj osobný dojem?
C je jednoduchoučký jazyk, ve kterém je zatraceně těžké programovat ;)

Je jednoduchý, protože je to jazyk z kompilátorové doby kamenné. To, co umí a co tedy musí umět překladač je osekané na naprosté minimum. Proto má každý krumpl překladač Cčka. Napsat základní překladač je fakt jednoduché.

Z toho plyne první peklo. Překladač neudělá skoro nic. Všechno je na tobě jako programátorovi. Včetně tupé mechanické dělničiny, kterou my lidi umíme podstatně hůř než stroje. Takže nám to dýl trvá, zato tam nasekáme kopec zbytečných chyb. ;)

Druhé peklo je v tom, že i to co umí je plné (z dnešního pohledu) zbytečných komplikací a pastí. Jeden příklad za všechny:
- Jako programátor máš za úkol zajisti aby ti sečtení intů nikdy nepřeteklo. Jinak je to undefined behavior a můžou se dít fakt divné věci. Už jsi někdy krokoval časoprostorovou anomálii?
- Dostaneš nulovou podporu pro to, abys to zajistil. Jazyk C je high level assembler, ve kterém není add with carry. Schválně si to zkuste ve standardním C napsat. Ano, asi tak všechny překladače pro to mají nějakou intrinsiku, páč se bez toho funguje fakt blbě.

Z toho plyne jeden zajímavý praktický důsledek. Nikdo nepíše v C. Vždycky je to nějaký dialekt, protože bez nadstandardních rozšíření se v tom jazyce nedá fungovat. A samozřejmě, že mezi těmi dialekty jsou občas dost zásadní rozdíly.

Ono je zakazano pouzivat knihovny?
Aritmetiku s velkymi cisly resi gmp knihovna. Proc znovuvynalezat kolo?
https://gmplib.org/

Tak treba lidi co delaji linux v C pisou.

Ja v C taky pisu a je to muj nejoblibenejsi jazyk.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #34 kdy: 03. 06. 2025, 10:59:48 »
Pravda. Spravne se to ma napsat.
Kód: [Vybrat]
printf("%u\n", ((uint16_t)-1) >> 1);

spravne (a bez specifikace bitove sirky) takto:
Kód: [Vybrat]
~0u >> 1


Re:Je jazyk C skutočne ťažký?
« Odpověď #35 kdy: 03. 06. 2025, 11:08:57 »
Ahoj, moja otázka je veľmi jednoduchá. Je jazyk C skutočne ťažký alebo to je iba môj osobný dojem?

- Dostaneš nulovou podporu pro to, abys to zajistil. Jazyk C je high level assembler, ve kterém není add with carry. Schválně si to zkuste ve standardním C napsat. Ano, asi tak všechny překladače pro to mají nějakou intrinsiku, páč se bez toho funguje fakt blbě.

Ve standardní knihovně v stdckdint.h je ckd_add

Re:Je jazyk C skutočne ťažký?
« Odpověď #36 kdy: 03. 06. 2025, 11:23:53 »
Tak treba lidi co delaji linux v C pisou.

Ja v C taky pisu a je to muj nejoblibenejsi jazyk.
Linux není psaný v C ale v GCC dialektu. Portování do clangu se provedlo tak, že do clangu přidali nezbytnou část gcc dialektu ;)

Ve standardní knihovně v stdckdint.h je ckd_add
Ejhle, novinka :) Umí to někdo jiný než clang? V godboltu jsem to jinde nerozjel. To je i __builtin_add_overflow  přenositelnější.

Re:Je jazyk C skutočne ťažký?
« Odpověď #37 kdy: 03. 06. 2025, 11:34:30 »
spravne (a bez specifikace bitove sirky) takto:
Kód: [Vybrat]
~0u >> 1
O tom, jestli je to správně by se dalo diskutovat dlouho. Hlavně proto, že nemáme zadání, co má ten program vypsat. Čěkal bych, že správné chování by se pokud možno nemělo lišit mezi platformama.

Re:Je jazyk C skutočne ťažký?
« Odpověď #38 kdy: 03. 06. 2025, 11:36:05 »
Ono je zakazano pouzivat knihovny?
Aritmetiku s velkymi cisly resi gmp knihovna. Proc znovuvynalezat kolo?
https://gmplib.org/
GMP není úplně vhodné řešení, když počítám s jednoregistrovými čísly a akorát potřebuju nějak pořešit přetečení.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #39 kdy: 03. 06. 2025, 11:42:21 »
C zachovava pri rotaci znamenko protoze rotace je provadena na znamenkovem typu, dela tedy tzv. aritmeticky bit shift.
Ani náhodou. Right shift na signed integeru je v C implementation defined. Překladač to může přeložit jako arimetický, nebo jako logický shift. Výsledek bude samozřejmě úplně jiný. Ke zbytku toho, co jsi napsal, se nebudu vyjadřovat, je to stejně nesprávné jako tvoje tvrzení, že je to aritmetický bit shift.

Nerekl jsem ze to neni implementation defined. Naopak to zakonite musi byt implementation defined, protoze reprezentace signed cisel neni nijak specifikovana a samotna je implementation defined. Muze byt pres dvojkovy doplnek (jak uz jsem psal v tom zbytku co jsi necetl) a muze byt i jinak.

Proto nema smysl vubec ani neco takoveho psat - rotaci na signed cisle. Ja jsem vzdy delal veskere bitove operace na unsigned typech a nikdy jsem s tim nemel problem. Kdo se chce strelit do nohy, toho C samozrejme necha, protoze neobsahuje zadne vozeni za rucicku. Z tohoto pohledu je tedy C tezky jazyk - clovek musi presne vedet jak to dole funguje.

Cely ten pripad s rotaci signed integeru mi prijde jako umele vykonstruovany priklad ktery jsem treba ja v praxi nikdy nemel,  nevim jak ostatni... Ale dava to smysl proc to tak je a tezko si predstavit ze by to melo byt jinak.

Re:Je jazyk C skutočne ťažký?
« Odpověď #40 kdy: 03. 06. 2025, 11:44:32 »
Ve standardní knihovně v stdckdint.h je ckd_add
Ejhle, novinka :) Umí to někdo jiný než clang? V godboltu jsem to jinde nerozjel. To je i __builtin_add_overflow  přenositelnější.

Ještě to umí GCC od 14.1, ale snad se přidají i další, když už je to ve standardu.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #41 kdy: 03. 06. 2025, 11:45:21 »
spravne (a bez specifikace bitove sirky) takto:
Kód: [Vybrat]
~0u >> 1
O tom, jestli je to správně by se dalo diskutovat dlouho. Hlavně proto, že nemáme zadání, co má ten program vypsat. Čěkal bych, že správné chování by se pokud možno nemělo lišit mezi platformama.

tak predpokladam ze zadani je udelat bitovy shift o jedno misto doprava... toto je prave stejne chovani napric vsema platformama protoze zaprve to pouziva ~0 misto -1 (ktere se muze lisit tam kde nejsou signed cisla implementovany dvojkovym doplnkem) a zadruhe je oprace provadena na unsigned integeru (0u), cili tam je jasne definovane jaky bude vysledek.

Re:Je jazyk C skutočne ťažký?
« Odpověď #42 kdy: 03. 06. 2025, 11:52:19 »
Cely ten pripad s rotaci signed integeru mi prijde jako umele vykonstruovany priklad ktery jsem treba ja v praxi nikdy nemel,  nevim jak ostatni... Ale dava to smysl proc to tak je a tezko si predstavit ze by to melo byt jinak.
To je tvůj problém, že bitovým rotacím nerozumíš. Arithmetic right shift na signed čísle je jasně definovaný a je přesně dané, co to dělá a jsou na to CPU instrukce. Problém C je v tom, že přesně nedefinuje, co má rotace na signed čísle dělat. Standard dává možnost přeložit to jako aritmetický, nebo logický shift. Je to jeden z tisíce způsobů, jak se v C střelit do nohy, protože většína lidí předpokládá, že je to arimetický shift. Ale nemusí být, když to překladač C přeloží jako logický shift, je to taky podle C standardu v pořádku.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #43 kdy: 03. 06. 2025, 11:56:48 »
Ono je zakazano pouzivat knihovny?
Aritmetiku s velkymi cisly resi gmp knihovna. Proc znovuvynalezat kolo?
https://gmplib.org/
GMP není úplně vhodné řešení, když počítám s jednoregistrovými čísly a akorát potřebuju nějak pořešit přetečení.

Tak jasne no, C jako takove nerekne jestli operace pretece nebo ne - nema pristup k Carry flagu. Rekl bych ze to je opet proto ze ne vsechny architektury resi carry flag stejne. Mozna jsou i nejake ktere ho nemaji vubec. C musi byt prenositelne, to je jeho zakladni vlastnost.
Ale moznost jak detekovat preteceni v C existuje, clovek si muze lehce napsat funkci ktera mu rekne jestli vysledek scitani pretece nebo ne. Druha moznost je to implementovat pomoci assembleru a udrzovat header pro vsechny podporovane architektury - ta moznost tu je. Ale neni toto problem ve vsech jazycich? Je nejaky jazyk ktery nativne vyuzije carry flag? Nevolaji vsechny jen nejakou funkci ktera detekuje preteceni, podobne jako treba tato funkce v C?
Kód: [Vybrat]
bool will_addition_overflow(unsigned int a, unsigned int b)
{
    return a > UINT_MAX - b;
}

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #44 kdy: 03. 06. 2025, 11:57:56 »
Cely ten pripad s rotaci signed integeru mi prijde jako umele vykonstruovany priklad ktery jsem treba ja v praxi nikdy nemel,  nevim jak ostatni... Ale dava to smysl proc to tak je a tezko si predstavit ze by to melo byt jinak.
To je tvůj problém, že bitovým rotacím nerozumíš. Arithmetic right shift na signed čísle je jasně definovaný a je přesně dané, co to dělá a jsou na to CPU instrukce. Problém C je v tom, že přesně nedefinuje, co má rotace na signed čísle dělat. Standard dává možnost přeložit to jako aritmetický, nebo logický shift. Je to jeden z tisíce způsobů, jak se v C střelit do nohy, protože většína lidí předpokládá, že je to arimetický shift. Ale nemusí být, když to překladač C přeloží jako logický shift, je to taky podle C standardu v pořádku.

pouze u signed cisel, u unsigned je operace definovana exaktne... mozna bys mohl mene urazet a vice chapat... neni to zadny problem, protoze provadet takove operace na signed cislech je implementation defined z podstaty, protoze samotna signed aritmetika je implementation defined
« Poslední změna: 03. 06. 2025, 12:00:19 od vrit »