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

Re:Je jazyk C skutočne ťažký?
« Odpověď #165 kdy: 11. 06. 2025, 10:27:29 »
A jak zapíšu do registru který je na adrese 0x00000000
Nezapíšeš. Protože gcc ti na tohle, v závislosti na optimalizacích, verzi překladače a fázi měsíce vygeneruje ud2 isntrukci. A proč? Protože může, je to undefined behavior, norma takové chování povoluje.

https://godbolt.org/z/bGqsEqsYc


Re:Je jazyk C skutočne ťažký?
« Odpověď #166 kdy: 11. 06. 2025, 10:44:41 »
A jak zapíšu do registru který je na adrese 0x00000000
Nezapíšeš. Protože gcc ti na tohle, v závislosti na optimalizacích, verzi překladače a fázi měsíce vygeneruje ud2 isntrukci. A proč? Protože může, je to undefined behavior, norma takové chování povoluje.

https://godbolt.org/z/bGqsEqsYc
Tohle je ještě dobrý. Crash by člověk tak nějak čekal.
Lepší je, když to přiřazení překladač využije jako informaci, že ten pointer nemůže být NULL.
A ještě lepší je čtení, které pak třeba může taky zmizet.  :o
https://godbolt.org/z/qxKhYThY6

Re:Je jazyk C skutočne ťažký?
« Odpověď #167 kdy: 11. 06. 2025, 10:47:47 »
Na adresu 0 zapsat jde, pokud tam je mapována stránka.
Ještě na WinXP šlo namapovat nultou stránku z user space, ale vznikaly tím security díry, na nových widlích to jde jen z kernelu.
Třeba DOS emulátor potřebuje validní nultou adresu.

Re:Je jazyk C skutočne ťažký?
« Odpověď #168 kdy: 11. 06. 2025, 10:53:45 »
To, co tu tvrdíme už nějakou dobu. Nechat C jen tam, kde je to nezbytně nutné. A tam, kde chceš performance, ale není nutně důvod použít C, použít třeba Rust. Který dá +- podobný výkon, ale z principu vyloučí velmi časté chyby z C.

Proč lidi tolik trvají na tom, že i šroub musí zatlouct kladivem, jen proto, že je to o něco rychlejší, než najít ten šroubovák?  :D

Ono psát nějaké datové struktury v Rustu je celkem chuťovka. Ve standardní knihovně se k tomu používá unsafe Rust a opět vám hrozí nedefinované chování kvůli aliasingu. Navíc řešíte řešíte problémy, které v C nejsou, jako například, jak vhodně použít PhantomData.


Protože ty problémy v C jsou. Schované. Rust Vás jen donutí je explicitně pojmenovat a vyřešit.

Když píšete vlastní datovou strukturu v Rustu stylem jako ve standardní knihovně, tak používate unsafe Rust a kompilátor vám s tím moc nepomůže (naopak tam jsou občas větší špeky než v C - to je aspoň můj subjektivní názor).

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #169 kdy: 11. 06. 2025, 11:00:53 »
A jak zapíšu do registru který je na adrese 0x00000000
Nezapíšeš. Protože gcc ti na tohle, v závislosti na optimalizacích, verzi překladače a fázi měsíce vygeneruje ud2 isntrukci. A proč? Protože může, je to undefined behavior, norma takové chování povoluje.

https://godbolt.org/z/bGqsEqsYc

Tak překladač má být správně nastaven podle toho co dělám...
Kód: [Vybrat]
-O2 -fno-delete-null-pointer-checks
https://godbolt.org/z/TTfc87sxb

Kód: [Vybrat]
test():
        mov     DWORD PTR ds:0, 1
        ret


Re:Je jazyk C skutočne ťažký?
« Odpověď #170 kdy: 11. 06. 2025, 11:01:27 »
Proto vznikají články jako už zmíněný https://floooh.github.io/2018/06/17/handles-vs-pointers.html , proto máme valgrind (a taky glib nebo Qt/QML pro C++).

Tohle se může použít i v Rustu, když implementujete pool a chcete věděť jaké z hodnot jsou ještě použitelné a jaké ne. Protože třeba u pole či vektoru kompilátor Rustu neumí sledovat, jaká podmnožina indexů obsahuje platnou hodnotu, nebo kde se hodnota vyměnila.

Re:Je jazyk C skutočne ťažký?
« Odpověď #171 kdy: 11. 06. 2025, 11:14:41 »
Když píšete vlastní datovou strukturu v Rustu stylem jako ve standardní knihovně, tak používate unsafe Rust a kompilátor vám s tím moc nepomůže (naopak tam jsou občas větší špeky než v C - to je aspoň můj subjektivní názor).

Jen pokud nutně potřebujete speciální pointery.

On je trošku problém, že se v Rustu snaží hodně lidí psát jako by to bylo C (protože na něj z C přešli). Jsou případy, kdy to může být nutné, ale většina lidí nepíše nový typ datové struktury nebo nový async executor každý den.

(A)Rc a Weak by mělo pro většinu účelů s referencemi bohatě stačit.

Jo, pokud píšete no_std embedded kód bez heapu, tak to začíná být zajímavější. To přiznávám. Ale to bylo i to C.

Abychom se vrátili k tématu. C je těžké a občas dává programátorovi pocit, že to má pod kontrolou, i když něco přehlédl. Rust je těžký, protože za to přehlédnutí programátorovi vynadá. A oba jazyky dávají v "unsafe" režimu možnosti jak udělat něco nedovoleného.

Možná bychom to mohli zobecnit na.. programování je těžké a nemusíme si přidělávat práci ještě použitím nevhodného jazyka. Základy domu taky nekopu lžící a použiju bagr.

Re:Je jazyk C skutočne ťažký?
« Odpověď #172 kdy: 11. 06. 2025, 11:15:44 »
Na adresu 0 zapsat jde, pokud tam je mapována stránka.
V assembleru jo. Ale v C (bez nějakých nadstandardních flagů) to nesmíš. Takže ten vygenerovaný kód občas vypadá dost překvapivě.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #173 kdy: 11. 06. 2025, 11:21:43 »
No blbě. Pokud to vaše platforma potřebuje, tak vám musí dát nějaký nestandardní způsob jak to udělat. Standardní C to neumí (pokud teda NULL odpovídá adrese 0, to taky nemusí platit).
Nesmysl. Standardní C to umí a vždy se to dělalo přes pointer, pokud jste někdy viděl nějakou knihovnu pro mikrokontroléry, tak tam se nastavují registry takto běžně, třeba AVR.

Správný postup je napsat všechno bez chyb. Jenže my lidi to jaksi neumíme. A proto tu řešíme co mi jazyk udělá, když se seknu a něco neohandlím.
Tohle není chyba, tohle je zásadní neznalost že datový typ nemůže nabývat neomezeného počtu hodnot a má horní a spodní limit. A když má horní limit a přičítám číslo 1, tak zákonitě musím operaci povolit jen v rozmezí po horní limit - 1. To je realita s kterou musí pracovat každý programátor, který má fixní datové typy, toto neplatí pouze pro C, vychází to z toho že proměnná má určitou bitovou šířku a může mapovan omezený půočet hodnot. To je základní znalost v programování.

Je to jen další "wishful programming" kde si programátor přeje aby měl něco jiného než reálně má.

Jestli někdo ani toto nemá, tak ať se C raději vyhne a nechá pracovat ty kteří tomu rozumí a umí to napsat bez chyb.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #174 kdy: 11. 06. 2025, 11:34:42 »
V assembleru jo. Ale v C (bez nějakých nadstandardních flagů) to nesmíš. Takže ten vygenerovaný kód občas vypadá dost překvapivě.

A proč bych to jako nesměl? C není nijak limitované na prostředí kde je nějaký operační systém. V C lze psát jak high-level aplikace tak i low-level drivery které zapisují/nebo čtou na/z fixních adres. Takže nějakému "to nesmíš" se nezbývá než pozasmát. V embedded se takto programuje naprosto běžně...

V C lze psát jak portabilní kód, tak specifický kód pro nějakou architekturu. Podporuje i inline assember instrukce.

Re:Je jazyk C skutočne ťažký?
« Odpověď #175 kdy: 11. 06. 2025, 11:51:04 »
No blbě. Pokud to vaše platforma potřebuje, tak vám musí dát nějaký nestandardní způsob jak to udělat. Standardní C to neumí (pokud teda NULL odpovídá adrese 0, to taky nemusí platit).
Nesmysl. Standardní C to umí a vždy se to dělalo přes pointer, pokud jste někdy viděl nějakou knihovnu pro mikrokontroléry, tak tam se nastavují registry takto běžně, třeba AVR.
Fakt byste se měl podívat, co umí standardní C a co je nadstandardní rozšíření vašeho GCC dialektu.

Dost z toho, co jste tady napsal dělá jen GCC, protože to vůbec není součástí standardního C.

Re:Je jazyk C skutočne ťažký?
« Odpověď #176 kdy: 11. 06. 2025, 12:07:34 »
A jak zapíšu do registru který je na adrese 0x00000000
Nezapíšeš. Protože gcc ti na tohle, v závislosti na optimalizacích, verzi překladače a fázi měsíce vygeneruje ud2 isntrukci. A proč? Protože může, je to undefined behavior, norma takové chování povoluje.

https://godbolt.org/z/bGqsEqsYc

Tak překladač má být správně nastaven podle toho co dělám...
Kód: [Vybrat]
-O2 -fno-delete-null-pointer-checks
https://godbolt.org/z/TTfc87sxb

Kód: [Vybrat]
test():
        mov     DWORD PTR ds:0, 1
        ret
-fno-delete-null-pointer-checks je nestandardní gcc rozšíření. Otázka zněla, jak ve standardním C zapsat na adresu 0. Odpověd je, že to ve standardním C NELZE, protože dereference null pointeru je dle C standardu undefined behavior.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #177 kdy: 11. 06. 2025, 12:40:02 »
A jak zapíšu do registru který je na adrese 0x00000000
Nezapíšeš. Protože gcc ti na tohle, v závislosti na optimalizacích, verzi překladače a fázi měsíce vygeneruje ud2 isntrukci. A proč? Protože může, je to undefined behavior, norma takové chování povoluje.

https://godbolt.org/z/bGqsEqsYc

Tak překladač má být správně nastaven podle toho co dělám...
Kód: [Vybrat]
-O2 -fno-delete-null-pointer-checks
https://godbolt.org/z/TTfc87sxb

Kód: [Vybrat]
test():
        mov     DWORD PTR ds:0, 1
        ret
-fno-delete-null-pointer-checks je nestandardní gcc rozšíření. Otázka zněla, jak ve standardním C zapsat na adresu 0. Odpověd je, že to ve standardním C NELZE, protože dereference null pointeru je dle C standardu undefined behavior.

To nema s GCC nic společného. Takhle se psalo jestě než nějaký GCC vůbec existoval. A ani to nemá nutně nic společného s adresou 0. Prostě obecně když mám pointer a přectu přes něj nebo zapíšu, tak čtu nebo zapisuju z nějaké adresy v paměti která odpovídá hodnotě pointeru. Tady nic nestandardního není.

To proč je to undefined behaviour je, protože záleží na runtime environment co takový zápis nebo čtení způsobí. Na té adrese může být registr jehož vyčtením se vyclearujou flagy, nebo to může být obyčejná paměťová buňka. Ale to je undefined behaviour v obecné rovině. To vůbec neznamená že to nemůžu pro architecture (environment) specific kód použít a už vůbec to neznamená že by se nemělo na adresu zapsat nebo z ní přečíst když použiju pointer.

Kód: [Vybrat]
uint32_t *p_u32 = 0x00000040;
*p_u32 = 0x12345678; // zapiš hodnotu 0x12345678 na adresu 0x00000040

Toto je naprosto legitimní C-kód, sic platform specific.
« Poslední změna: 11. 06. 2025, 12:41:37 od vrit »

Re:Je jazyk C skutočne ťažký?
« Odpověď #178 kdy: 11. 06. 2025, 13:03:33 »
Kód: [Vybrat]
uint32_t *p_u32 = 0x00000040;
*p_u32 = 0x12345678; // zapiš hodnotu 0x12345678 na adresu 0x00000040

Toto je naprosto legitimní C-kód, sic platform specific.

To není tak úplně pravda. Tohle je legální jen s "volatile". Jinak bude optimalizátor provádět psí kusy.

Re:Je jazyk C skutočne ťažký?
« Odpověď #179 kdy: 11. 06. 2025, 13:10:54 »
To nema s GCC nic společného. Takhle se psalo jestě než nějaký GCC vůbec existoval. A ani to nemá nutně nic společného s adresou 0. Prostě obecně když mám pointer a přectu přes něj nebo zapíšu, tak čtu nebo zapisuju z nějaké adresy v paměti která odpovídá hodnotě pointeru. Tady nic nestandardního není.
Pořád tomu nerozumíš. Nevadí, zkusím to vysvětlit znovu. null pointer (adresa 0) se v C standardu ošetřuje speciálně. C standard explicitně říká, že dereference null pointeru je undefined behavior. Tozn. pokud máš v C programu čtení nebo zápis adresy 0, překladač s tím může udělat cokoliv (a taky dělá). Může to ignorovat, může vygenerovat neplatnou instrukci, může to dokonce i fyzicky provést. Jakékoliv chování, včetně všech zmíněných, je při dereferenci null pointeru legální.