A cím talán kissé érthetetlen de féltem nem férne bele a limitbe ha alaposan kimagyarázom ott...
Tehát, a bajom az hogy én szinte mindig C nyelven programozom, és úgy szeretném beállítani a gcc illetve g++ progit (nekem aztán teljesen mindegy hogy parancssori kapcsolóval vagy makefile által vagy bárhogy, csak legyen rá mód!) hogy ilyesmiket ne lehessen csinálni:
for(i=0;i<max;i++) a[i]=b[i];
Hanem csak ezt:
for(i=0;i<max;i++) {a[i]=b[i];}
azaz KÖVETELJE MEG a kapcsos zárójelek kitételét EGYETLEN utasítás esetén is!
Ugyanez igaz az if esetére is: ilyet NE lehessen:
if(a>b) g++;
Hanem csak így:
if(a>b) {g++;}
Tehát mindig, MINDIG követelje ki a kapcsos zárójeleket ilyenkor, egyetlen utasítás esetén is! És ne is warningoljon, hanem ha nincs ott, akkor simán ERROR és kész. Ne legyen hajlandó lefordítani. Léccike segítsetek! Ez az egyik legbosszantóbb hibája a C nyelvnek, hogy ilyesmiket megenged. Teljesen áttekinthetetlenné tudja tenni a kódot. Számtalan hibalehetőség forrása. Bevallom, semmiféle lehetőséget nem találtam ennek beállítására, pedig sokat keresgéltem.
- 1538 megtekintés
Hozzászólások
Főleg a nem konzisztens indentálás miatt zavar ez téged, nem?
Ha minden mentéskor meghívnád a clang-formatot is a kedvenc coding styleoddal, akkor is zavarna?
- A hozzászóláshoz be kell jelentkezni
"Tehát, a bajom az hogy én szinte mindig C nyelven programozom"
Akkor ideje lenne végre megtanulni azokat a nyelvi eszközöket is, amik szintén a nyelvhez tartoznak. Az, hogy ez téged összezavar, nem a nyelv problémája.
A fordító meg ilyet nem fog tudni, amit te szeretnél, az egy format checker, azt meg úgy paraméterezed ahogy szeretnéd
// Happy debugging, suckers
#define true (rand() > 10)
- A hozzászóláshoz be kell jelentkezni
Akkor ideje lenne végre megtanulni azokat a nyelvi eszközöket is, amik szintén a nyelvhez tartoznak. Az, hogy ez téged összezavar, nem a nyelv problémája.
-1
Nalunk az ilyen kodot peer review-n vissza szokas kuldeni, mert rohadtul zavaro, akkor is, ha ismered ezeket a rejtelyes "nyelvi eszközöket".
- A hozzászóláshoz be kell jelentkezni
Ha ezek számodra "rejtélyes nyelvi eszközök", az sem a nyelv problémája. Az meg hogy *review -en ez visszaküldésre kerül, az ismételten csak az éppen aktuálisan alkalmazott programming style kérdése és nem nyelvi
// Happy debugging, suckers
#define true (rand() > 10)
- A hozzászóláshoz be kell jelentkezni
Ha ezek számodra "rejtélyes nyelvi eszközök"
Szamomra? Arra reagaltam, hogy "ideje lenne végre megtanulni azokat a nyelvi eszközöket is, amik szintén a nyelvhez tartoznak". Oke, tfh megtanulta. Attol meg nem kotelezo gondolkodas nelkul mindent eszkozt hasznalni, csak mert supported. :)
Mi elonye van "elfelejteni" a kapcsos zarojeleket? Oke, megsporolsz par tucat bajtot, es? Mert hatranya viszont van, megpedig az, hogy eleg konnyen be lehet szopni, foleg a kevesbe gyakorlottaknak, ha hozza kell nyulni. Megeri?
Az meg hogy *review -en ez visszaküldésre kerül, az ismételten csak az éppen aktuálisan alkalmazott programming style kérdése és nem nyelvi
Egy szoval nem mondtam, hogy nyelvi okok miatt. :)
- A hozzászóláshoz be kell jelentkezni
A secure coding guide-okban is gyakori vendég ez, nem kevés program biztosított már hátsó bejárót emiatt. :)
- A hozzászóláshoz be kell jelentkezni
Tehát, a bajom az hogy én szinte mindig C nyelven programozom
Ha ez a bajod (megértem, miért baj), miért nem váltasz másik nyelvre? :)
BlackY
"Gyakran hasznos ugyanis, ha számlálni tudjuk, hányszor futott le már egy végtelenciklus." (haroldking)
- A hozzászóláshoz be kell jelentkezni
Jaj ne már!
Két jól irányzott szabályos kifejezéssel lehet írni egy shellszkriptet (héjprogramot :-) ) ami fordítás előtt kiszűri a "problémát".
- A hozzászóláshoz be kell jelentkezni
miért nem váltasz másik nyelvre? :)
Miert valtana masik nyelve?
- A hozzászóláshoz be kell jelentkezni
Szerintem próbálj meg nem egy félmondatot kiragadni, hanem egészében értelmezni a szarkasztikus megjegyzést.
- A hozzászóláshoz be kell jelentkezni
Mert azt állítja, hogy az a baja, hogy mindig C nyelven programozik ;) (ahogy fentebb írták, nézd meg, hogy melyik részletet ragadtam ki a nyitóból)
BlackY
"Gyakran hasznos ugyanis, ha számlálni tudjuk, hányszor futott le már egy végtelenciklus." (haroldking)
- A hozzászóláshoz be kell jelentkezni
Ez nem az ő baja, hanem a miénk...
- A hozzászóláshoz be kell jelentkezni
Teljesen áttekinthetetlenné tudja tenni a kódot.
Nekem annó azt tanították, hogy a goto az amivel a kód átláthatatlan lesz, nem a fenti probléma :D
Fedora 41, Thinkpad x280
- A hozzászóláshoz be kell jelentkezni
A goto ugyan úgy szükséges nyelvi elem. Pl. nézz meg egy probe függvényt a Linux kernelben.
- A hozzászóláshoz be kell jelentkezni
A goto alapjában véve kerülendő elem. Alapvetően igaz, hogy NE HASZNÁLD!
Nagyon kevés speciális eset van, amikor viszont előnyös. Egyszer én is belefutottam, amikor spéci architektúra utasítás emulátorát írtam és kellett a tempó. A switch()-es és egyéb calltable-s megoldást tempóban hamar kiütötte az alábbi:
instr_VALAMI:
// itt van a VALAMI utasítás token végrehajtása
goto *prog[++progct].instr; // következő utasítás kiértékelőjére közvetlenül ugrunk
De szigorúan csak az interpreter ezen részében használtam és kommentezve.
Esetleg valaki tud hasonló esetet, amikor sokat gyorsít?
- A hozzászóláshoz be kell jelentkezni
Nem a gyorsításon van a hangsúly (persze ez is érv mellette amúgy), hanem az olvasható és karbantartható kódon (igen, a goto-ról beszélek). A linux kernelben több, mint 100.000x van leírva, hogy goto. De nem összevissza, mindenre használják, hanem nagyrészt egy ok miatt: hibakezelés. És eléggé igazuk van.
Ha gondolod, válassz ki egy olyan fv-t, amiben sok label, goto van. És írd át goto nélkülire. Meg fogod látni, hogy nagyobb lesz a kód, és lassabb (ha esetleg nem, akkor szerencséd volt, és pont egy olyan fv-t választottál ki, amire ez épp nem igaz). Vagy olvashatatlanabb a nagy indentáció miatt. Amit a linux kernelben látsz, egy hibakezelési módszer. Lehet, hogy olyan helyeken is alkalmazzák, ahol egyszerűen el lehetne kerülni a goto-t. De gondolom nem akarnak összevisszaságot. Meg így karbantarthatóbb (lehet, hogy egy fv egyszerű, és goto nélkül is meg lehet oldani. De aztán bonyolódik, és akkor már kell a goto. Akkor írhatod át goto-sra).
- A hozzászóláshoz be kell jelentkezni
A hibakezelésen elgondolkoztam. Nagy kódban tényleg praktikus lehet arra. Hiszen sok apró helyről kell eljutni egyetlen hibaágba és onnan lezárni vagy újrainicializálni.
- A hozzászóláshoz be kell jelentkezni
Ha a programozó tudja, hogy mit csinál, akkor nem számít, hogy goto
van a kódjában, ha pedig nem tudja, akkor nem számít, hogy nincs.
- A hozzászóláshoz be kell jelentkezni
Naná hogy tudok. Például amikor egy többszörösen egymásbaágyazott ciklus„hierarchia” belsejéből kell kiugorni. Nem okvetlenül hiba miatt, lehet ez teljesen normális működés része is. na és ilyenkor a goto kincset ér! Ha nem gotoval akarod megoldani ezt a helyzetet, akkor mindenféle „köztes változók” meg „flagek” bevezetésére van szükséged amiknek állapotát minden ciklus vége után újra meg újra ellenőrizgetni kell, teljesen feleslegesen lassítva ezzel a programot, és elnyomorítva a program áttekinthetőségét.
Általánosságban azért én is azt mondom, a goto kerülendő. De ez is inkább a kezdőkre érvényes, aki még nem tudja szegénykém, mikor indokolt a goto használata és mikor nem az. Annak semmi esetre se vagyok híve, hogy egy programnyelvbnen eleve ne is legyen goto.
- A hozzászóláshoz be kell jelentkezni
Ezt én is egyszerűen run flag minden szinten való vizsgálatával oldottam meg, de az igény valósnak látszik, ugyanis a Rust szintén foglalkozik ezzel a kérdéssel:
fn main() {
'kulso: for i in 1..5 { // 'cimke
for j in 1..=5 {
println!("i: {} j: {}", i, j);
if i == 3 && j == 2 {
break 'kulso; // lehetőséged van cimkére is ugratni
}
}
}
}
- A hozzászóláshoz be kell jelentkezni
A címkére ugrás pont ugyanaz, mint a goto.
- A hozzászóláshoz be kell jelentkezni
Azzal a megkötéssel, hogy a cimkét nem rakhatod bárhova Rust esetén, csak közvetlenül a ciklus (while, for, loop) elé írhatod, mivel a célja a ciklus(okból) való kiugrás.
A { előtti megoldás még az elején tart, nem stabil, így arról keveset tudok.
fn main() {
'kulso: println!("Ez nem lesz okés"); // 'cimke ... ERROR lesz
for i in 1..5 {
for j in 1..=5 {
println!("i: {} j: {}", i, j);
if i == 3 && j == 2 {
break 'kulso; // lehetőséged van cimkére is ugratni
}
}
}
}
$ rustc teszt.rs error: expected `while`, `for`, `loop` or `{` after a label --> teszt.rs:2:13 | 2 | 'kulso: println!("Ez nem lesz okés"); | ^^^^^^^ expected `while`, `for`, `loop` or `{` after a label error: aborting due to previous error
- A hozzászóláshoz be kell jelentkezni
Én a változó nullazast tetetnem kötelezővé. Nem az érték adást a nullazast.
Aki másnak vermet ás, az stack pointer.
- A hozzászóláshoz be kell jelentkezni
Nagy-nagy +!
Én minden programba teszek Init() rutint, ami az összes globális változót alapértékre állítja, a stringeket kinullázza, stb. A nem globális változókat rutinon belül állítom be, mielőtt felhasználnám őket barmire is.
(Ezt a szokásomat még a 3 hónapig tartó Fortranos korszkomból hoztam.)
> Sol omnibus lucet.
- A hozzászóláshoz be kell jelentkezni
Ezt a szokásomat még a 3 hónapig tartó Fortranos korszkomból hoztam.
De jó neked, hogy csak 3 hónapig tartott... :-)
- A hozzászóláshoz be kell jelentkezni
GATE, számtech és alkalmazott matek tanszék, ODRA, lyukszalagos rögzítés, beadandó feladat(-::
> Sol omnibus lucet.
- A hozzászóláshoz be kell jelentkezni
A Fortan, 3 hónap,számtech, ODRA, lyukszalagos rögzítés, beadandó feladat stimmel. Egyedül GATE --->BME
Ahogy öregszem egyre szebb lesz.
- A hozzászóláshoz be kell jelentkezni
Mármint használtad, hogy a régebbi Fortranokban a változókat default 0-ra inicializálta? (Legalábbis az újabb szabványnak nem része.)
- A hozzászóláshoz be kell jelentkezni
Minek, ha nem kell, mert pl. utána felül lesz írva az egész?
- A hozzászóláshoz be kell jelentkezni
Így még átláthatóbb lenne:
if(a>b)
{
g++;
}
XD
És akkor lehetne még azon is elmélkedni, hogy a nyitó { új sorba kerüljön-e vagy legyen az if sorában, hány karakter legyen a behúzás, tab vagy space.
Először működjön a kód, és ha már semmi másra nem tudod elb*szni az idődet, akkor ráérsz ilyesmivel szuttyogni.
- A hozzászóláshoz be kell jelentkezni
Így még átláthatóbb lenne:
Actually, igen. Es amikor jon a nalad kevesbe penge junior, es be akarja tenni a h++-t, akkor nem fog figyelmetlensegbol olyat csinalni, hogy
if(a>b) g++; h++;
- A hozzászóláshoz be kell jelentkezni
programozzék Pythonban a szentem!
disclaimer: ha valamit beidéztem és alá írtam valamit, akkor a válaszom a beidézett szövegre vonatkozik és nem mindenféle más, random dolgokra.
- A hozzászóláshoz be kell jelentkezni
Engem az érdekelne hogy ilyen szintű junior pozícióban mennyit lehet keresni bruttóban manapság?
- A hozzászóláshoz be kell jelentkezni
Mi az az "ilyen szintu"? Itt arrol van szo, hogy valaki benez valamit. Ertem, hogy a hup-on mindenki elsore tokeletes C kodot ir, es ha mondjuk 5 ev mulva at kell irni, akkor fejbol emlekszik minden apro reszletre, de ne ebbol induljunk ki. Van olyan programozo is, aki nem ilyen jo.
Maskepp megfogalmazva a kerdest: miert jo, ha szandekosan olyan kodot irunk, amiben plusz hibalehetosegek vannak? A hangsuly a "szandekosan" reszen van.
szerk: ha nem szarkasztikusan ertendo a kerdes, akkor bocsanat :) Ebben az esetben egy junior C dev siman kaphat brutto 500-at, ha egyebkent ertelmes, es mutat nemi fejlodesi kepesseget.
- A hozzászóláshoz be kell jelentkezni
Ha igényes vagy a munkádra foglalkozol a formázással. És akkor az nem lesz időelbaszás meg szuttyogás, mert reflexből fog jönni. Ami meg nem, azon segít mentéskor az automatikus formázás.
Ha pedig mégis időelbaszás vagy szuttyogás a vége, akkor rosszul csinálod.
- A hozzászóláshoz be kell jelentkezni
( haroldking | 2020. 03. 07., szo - 21:41 )
A problémám azzal van hogy egyszerűen nem bírom megszokni, hogy egy nyelvnél a forráskód KÜLALAKJA(!!!!!), gyakorlatilag a behúzások - a szintaxis szerves részét képezik!
- A hozzászóláshoz be kell jelentkezni
Vagyis a nyitó kérdés a kapcsoszárójelekről automatikusan megoldódott?
- A hozzászóláshoz be kell jelentkezni
Amit a python megkövetel (a nyelv részévé tett olyasmit ami normális ember szerint csak külalak kéne legyen), az MEGNEHEZÍTI a nyelv használatát, azáltal, hogy rengeteg extra hibalehetőséget visz bele.
Amit én szeretnék, az szerintem nem extra külalak-téma nyelvi elemmé tétele, csak az hogy valami amit amúgyis használ a nyelv (a kapcsos zárójelek) az szigorúan kikövetelt legyen bizonyos olyan esetekben is amikor amúgy ott csak opcionális. És ez csökkentené a hibalehetőségek számát...
Azaz felesleges gúnyolódnod, a két eset távolról se ugyanaz!
- A hozzászóláshoz be kell jelentkezni
Nem lehetséges, hogy te az ún. konvencióról beszélsz?
A többi fejlesztővel megegyeztek, hogy eztán mindig kiteszitek a kapcsosokat, és mindenki tartja magát hozzá. Pont. Vagy ez nem működhet? Akkor a kódbuzeráló se fog. ;)
[Szerk:] Gondolom a napi csaptmunkában zavar téged, és nem egy valahonnan letöltött forráskódban látva idegesít... :)
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
Nem dolgozom csapatban. Igen, idegesít az ilyesmi a máshonnan letöltött forráskódokban is, de ha meglepő lesz is a legnagyobb bajom mégis a saját programjaimban van. Ugyanis bár én következetesen ki szoktam tenni a topiknyitóban említett esetekben a kapcsos zárójeleket, de nagyon ritkán azért előfordulhat hogy mégis elfelejtem - „hála” annak hogy mint itt fentebb valaki beletrollkodta a topikba, „meg kéne tanulnom” a nyelv eszközeit vagy valami ilyesmit... na én megtanultam ugye sok évvel ezelőtt, és ha nagyon ritkán is de néha előfordul hogy az ősi beidegződések „jönnek elő”... na és ezt utálom. Hibalehetőség, na!
Emellett mára már ott tartok hogy a szépérzékemet is sérti ha nem azonos a kódolási stílus, azaz nincs ott mindenütt a kapcsos, ahol szerintem lennie kéne.
De visszatérve a máshonnan letöltött kódokra: bár nem sok ilyet használok, de ha mégis, szeretem azokat is úgy átformázni ahogy nekem tetszik. Ebben sokat segítene, ha fordítási kísérlet esetén a compiler azonnal ordibálna hogy hova illene beszúrnom a kapcsos zárójeleket.
Nem kell ezt az egészet túlmisztifikálni, hogy hátha nem tudom hol nem kötelező a kapcsos zárójel, hátha nem tudom mi számít egy utasításnak, meg hogy hátha kezdő vagyok (szerintem épp amiatt szeretném ezt mert határozottan nem vagyok kezdő és emiatt tudom, miféle galibák okozója lehet az ilyesmi... de mindegy, nem akarok senkit meggyőzni, tőlem tarthat akárki kezdőnek, nem izgat... trollok úgyis jönnek mindig...), meg hogy csapatban dolgozom-e (nem tökmindegy? Én így szeretném valamiért és kész, az meg hogy mikor kivel programozom hadd legyen már az én ügyem, a téma szempontjából felesleges), meg az is felesleges hogy belemenni abba ennek mi a nköze a pythonhoz, meg még az is felesleges hogy biztassatok, szokjak át másik nyelvre.
Mindez mellékes és nem tartozik a tárgyhoz. Egy konkrét kérdést tettem fel:
VAN-E MÓD ARRA, hogy az általam felvázolt viselkedésre utasítsuk a C compilert?
Ennyi a kérdés. Ehhez képest minden más amiről e topikban eddig rengeteg hozzászólás érkezett, teljesen irreleváns.
Még az is irreleváns, meg lehet-e oldani valami regexp-szerű akármivel a kérdést. Ha nagyon akarom, simán írok én is e célra valamit. Igazából ha akarom, simán megírok egy C compilert is... Oké, biztos nem lesz olyan hatékony mint a jelenlegik, de azért tuti hogy működne. (nem, nem fogom megírni csak azért hogy bizonyítsak, más feladatok jobban érdekelnek. Ne higgye aki nem akarja... de állítom, simán meg tudnám írni. Ehhez képest ez a kapcsos zárójelezés egy jelentéktelen részletkérdés).
Viszont én reméltem, létezik e teljesen logikus igény kielégítésére valami kész megoldás. Szerintem illene hogy legyen. Ha mégsincs, a válasz a kérdésemre az hogy NINCS. Ha van, kéretik megmutatni.
Hogy nem ez a C nyelv legnagyobb baja? Én is tudom, na és? Minden erről való elmélkedés megint irreleváns mert nem az volt a kérdés mi a baja a C-nek úgy általában hanem konkrétan a felvetett probléma megoldásában kértem segítséget.
- A hozzászóláshoz be kell jelentkezni
> VAN-E MÓD ARRA, hogy az általam felvázolt viselkedésre utasítsuk a C compilert?
geza42 lent javasolta a -Wmisleading-indentation
kapcsolót, ami a félreérthető indentálásra warningot dob. A -Werror
kapcsoló pedig errort csinál egy adott warningtípusból, akár ebből is, azaz, ha a kettőt kombinálod, az pont azt fogja csinálni, amit kértél.
Tehát így kell fordítanod: cc valami.c -Wmisleading-indentation -Werror=misleading-indentation
- A hozzászóláshoz be kell jelentkezni
Well, ezt nem ismeri a gcc:
vz@Csiszilla /Releases/2014/U/Common/vz/LIB=>make pngdict
gcc -c -o __pngdict.o __pngdict.c
gcc -Wunknown-pragmas -Wredundant-decls -Wunreachable-code -Wmisleading-indentation __pngdict.c -lm -L/usr/X11R6/lib -lX11 -lXmu -lXext -o pngdict ; rm __pngdict.o;
gcc: error: unrecognized command line option ‘-Wmisleading-indentation’
Ami még csodálatosabb, a Google se:
A keresett kifejezés (-Wmisleading-indentation) egyetlen dokumentumban sem található meg.
- A hozzászóláshoz be kell jelentkezni
Ami még csodálatosabb, a Google se:
A keresett kifejezés (-Wmisleading-indentation) egyetlen dokumentumban sem található meg.
Keresd így: "Wmisleading-indentation"
Ha kötőjellel kezdesz egy kifejezést, azt a Google úgy értelmezi, hogy kizárni akarod a keresésből. Mivel más kulcsszót nem adtál meg, amit viszont meg akarnál találni, ezért ilyen fura eredményt kapsz.
- A hozzászóláshoz be kell jelentkezni
Köszi! Így valóban megtalálta.
- A hozzászóláshoz be kell jelentkezni
Works for me :D
ventura@lenovo-x220:/tmp$ gcc --version
gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
Megnéztem régebbi gcc-vel 4.4 el az nem ismeri. Mintha a 6 osnál jött volna be ez a feature.
Gondolom mivel, te nem nagyon frissíted a dolgokat, elég régi gcc-d lehet, ami nem tudja.
Fedora 41, Thinkpad x280
- A hozzászóláshoz be kell jelentkezni
Jaja! Az én gecicém ezt nem ismeri... Most fordíthatok egy új GCC csomagot magamnak...
- A hozzászóláshoz be kell jelentkezni
gecicém
Ügyes, ezen sokat gondolkodtál?
- A hozzászóláshoz be kell jelentkezni
Még csak nem is én találtam ki, évekkel ezelőtt olvastam valahol de nem emlékszem már rá melyik internetes oldalon. Konkrétan ott "gecicé" volt írva, én csak a birtokos személyragot raktam most hozzá.
Különben áttértem a 8.2.0 verziójú GCC használatára. Tetszik, sok újabb warninggal ajándékozott meg (ennek valóban örülök mert még jobb lehet a kód amit írok!), de sajnos nem minden esetben kiabál a kapcsos zárójelek miatt amikor pedig én azt szeretném hogy tegye. Néha igen, na ez is valami... de nem mindig.
- A hozzászóláshoz be kell jelentkezni
Ha a warningok hasznosak, akkor a C++/Rust/Ada fordítóié még inkább.
- A hozzászóláshoz be kell jelentkezni
Előbb-utóbb eljutsz te is oda, hogy a C mellett a Rust lesz neked is a másik barátod. A C-ben meglevő nem kevés problémát újragondoltak ebben a nyelvben, és bátran bevállalták a radikális szemléletváltást.
Nem csoda, hogy a hype-listán előkelő helyen van. Mielőtt megkérdezed: jól tudok C-ben is programozni. Nemrég Rust + C közös kódot írtam, mert a rádiófrekvenciás jel decimálására a C tempója verhetetlen.
Alább a kapcsos zárójel példa Rust esetén: $ cat teszt.rs fn main() { if 4 == 4 println!("Azonos"); } $ rustc teszt.rs error: expected `{`, found `println` --> teszt.rs:2:15 | 2 | if 4 == 4 println!("Azonos"); | -- ^^^^^^^------------ | | | | | expected `{` | | help: try placing this code inside a block: `{ println!("Azonos"); }` | this `if` statement has a condition, but no block error: aborting due to previous error
Odarakod a kapcsos zárójeleket, lefordul.
És hogy a kódnak egységes kinézete legyen, ne függjön a fejlesztő személyétől:
$ rustfmt teszt.rs
A rustfmt által javított kinézetű kód pedig ebben az esetben ilyen lesz:
fn main() {
if 4 == 4 {
println!("Azonos");
}
}
Cargo használatával további tool, amely a hülyeségre figyelmeztet:
$ cargo clippy
Checking t v0.1.0 (/tmp/hup/pelda)
error: equal expressions as operands to `==`
--> src/main.rs:2:8
|
2 | if 4 == 4 {
| ^^^^^^
|
- A hozzászóláshoz be kell jelentkezni
Biztos, hogy rust-ban nem tudod hasonló gyorsra, vagy gyorsabbra megírni?
http://cliffle.com/p/dangerust/
Ez egy érdekes cikksorozat, hogy hogyan írt át unsafe rustra egy c kódot, majd hogyan alakította át safe rustra, ráadásul még gyorsabb is lett a végén.
- A hozzászóláshoz be kell jelentkezni
A rustot eddig nem ismertem, és így ahogy mutatsz ezt-azt belőle, valóban rokonszenves a kicsike, ezt elismerem. Bevallom azonban, én most inkább ott tartok hogy (megint) írok egy saját programnyelvet... de az mégse lesz teljesen „saját”, hanem egyszerűen egy nekem tetsző FORTH implementáció...
Mert ugye, sokan tudják errefele rólam de azt hiszem írtam is már talán ebbe vagy egy másik topikba, hogy írogattam pár interpretert magamnak. Jó sokat, talán tucatnyit is... ilyen meg olyan „koncepciókat” valósítottak meg... Na és a végén oda lyukadtam ki, hogy bár megoldottam a programnyelv-író kezdők legborzalmasabb rémálmát is, a „kifejezéskiértékelést”, akár operátor-precedenciával akár anélkül, szóval nem arról van szó hogy erre képtelen ne lennék, de ennek ellenére, nekem bizony a talán legfapadosabb megoldás tetszik: az RPN szintaxis!
Gyakorlatilag tehát valami FORTH-szerű nyelv...
A legutóbbi nyelvem már különben RPN jellegű, stack-orientált tehát, még azt is kitaláltam teljesen magam hogy 2 stack kell, mert egy a visszatérési címek számára van fenntartva. Na aztán hogy jobban elmélyedtem a FORTH nyelvben, rájöttem, hogy hm, ellopták az ötletemet mert ez abban már rég így van...
Na innen jött akkor a „továbbgondolat”, hogy hm, akkor mi a rákért erőltetem én hogy legyen „saját” nyelvem, ha úgyis egy olyan nyelv tetszik ami már készen van?!
A baj az hogy a FORTH úgy ahogy van, mégse tetszik. Például nem tetszik egyáltalán, ahogy jelenleg a gforth esetén a lebegőpontos számokat kezeli. Én elvárom, ha egy számban tizedespont van, akár a legvégén is, az automatice double-nak legyen tekintve. Mármint annak amit a C tekint double-nek...
És még mondhatnék efféle dolgokat holott Forth terén még csak kezdőnek tartom magamat. (de rendeltem már 2 vastag angol szakkönyvet az Amazontól róla...)
Tehát azt hiszem következő nyelvem nem „saját” nyelv lesz, de annyiból igen hogy saját __implementáció__. Igyekszem majd amennyire csak lehet kompatibilis maradni a meglevő vagy legalábbis ismertebb Forth variánsokkal, de beleálmodom mindazt a sok roppant okosságot és szépséget is amit kiagyaltam. Majd meglátjuk, mire megyek vele.
Ez nem lesz egy sürgős project a részemről, előbb alaposan átnyálazom a megrendelt könyveket, s majd aztán...
Mindenesetre, ez perpillanat jobban érdekel mint a Rust.
- A hozzászóláshoz be kell jelentkezni
A FORTH-ban az a jó, hogy a nyelvi elemeket (szavakat) természetes módon felül lehet definiálni. Így FORTH nyelven tudsz olyan lebegőpontos kezelést (meg bármi mást) alkotni magadnak, amilyet akarsz. Én nagyon szerettem, kár, hogy mostanában nincs ilyen projektem.
- A hozzászóláshoz be kell jelentkezni
Ha már RPN, dc-ben írni programot sem semmi.
$ echo "....." | dc
Feltételes elágazások, regisztercserék FORTH-hoz hasonlóan elvégezhetőek. Azonban a stackes működés mellett van lehetőség regiszterek használatára is.
https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html
Ma hobbinak szép, én is belekóstoltam a FORTH-ba. Ellenben engem a C mellett a Rust fogott igazán meg. Amint már írtam, C lemásolása helyett merészen újragondolták. Sajnos ez a merész szemléletváltás a C utáni Rust tanulást nehezíti. További sikerek: hogyan gyorsítsunk Rust-tal Python-t illetve nekem rádiófrekvenciás jelfeldolgozásnál ha kell még tempó, C-vel házasítsunk Rustot. Frankón megy mindkettő.
- A hozzászóláshoz be kell jelentkezni
Hát én ezeket az IDE-re bízom. IDEA esetén Ctrl-Shift-Alt-L és minden ilyen lófaszt megcsinál, céges esetben van config repository lehetőség, ahonnan a projektfüggő mindenfélét le lehet húzni a projekttel együtt.
- A hozzászóláshoz be kell jelentkezni
A modern szoftver fejlesztésben a minőség biztosítás első lépcsője a "clean-code". Ehhez igazodva lett a pythonban nyelvi elem az indentálás, illetve mint hg2ecz bemutatta a rust -ban is hasonló a helyzet. Az C azokból az időkből származik amikor ez a bölcsesség még nem állt rendelkezésre, ezért itt a szemlélet más, a CC -t külső eszközökkel, illetve code-review -val kell kikényszeríteni.
A CC két részre bontható:
- coding-style: ami a forrás olvashatóságát célozza, és mint ilyen nagyrészt olyan dolgokat rögzít ami ízlés kérése. Pl. hol legyen space és hol ne. C -hez készült egy talicska ilyen tool, illetve egy csomó IDE -nek van beépített sajátja. Pl. Eclipse-CDT -ben nyomsz egy "CTRL+SHIFT+F" -et és máris megtörténik a csoda. Van 1-2 elterjedt, szabványosnak mondható stílus, pl. a Linux kernel féle, vagy a K&R, szerencsés lehet ezek egyikére rászokni. Ajánlom figyelmedbe az Universal Indent GUI -t a témakörben. Én legtöbbször az "Artistic Style" -t használom, de állítólag a clang-format jobb nála. Megemlíteném még a CheckPatch nevű toolt, ami ilyen jellegű hibák automatizált tesztelésére való.
- Coding parctices: olyan programozási fogások gyűjteménye, melyek a tipikus programozási hibák elkerülését célozzák (hogyan csináld, illetve hongyan ne). C -ben az undefined behavior, illetve az implementation defined behavior a fő ellenség, azaz a nyelv olyan mechanizmusai amelyek működése specifikáció szerint nem definiált. Ide tartozik sok más buktató is, mint pl. az integer promotion, vagy az implicit casting finomságai, a nem inicializált változók tiltása, stb... A MISRA-C szabvány sok mindent definiál ebben a témakörben.
Ezen témakör ellenőrzésére valók a static analyzer -ek. Bonyolult eszközök ezek, általában 1-2 talicska pénzért adják őket, bár ma már a fordítók is elég jól ellenőriznek ilyesmit. Vannak ingyenes programok, pl. a clang-tidy vagy a CppCheck, illetve 1-2 nagy játékos ingyenesen használható open-source fejlesztésben (pl. Coverity Scan).
További olvasnivaló pl. itt: https://en.wikipedia.org/wiki/Coding_conventions
- A hozzászóláshoz be kell jelentkezni
Az a kisebbik baj a C szintaxisú nyelvekkel, hogy olyat megengednek, hogy
for(i=0;i<max;i++) a[i]=b[i];
Az sokkal nagyobb baj, hogy ezt is megengedik:
for(i=0;i<max;i++);
{
a[i]=b[i];
}
- A hozzászóláshoz be kell jelentkezni
További C hibalista (teljesség igénye nélkül), amit a Rust-ban javítottak:
- K&R közül egyik nyilatkozta tizenpár éve: bánja hogy nulltermináltra tervezték a stringet C-ben. A hibák melegágya lett. Rust: hosszt számlálja. Mellékes előny: daraboláskor Vec<&str> --> bárhol beléphetsz a String-be N hosszban, azaz daraboláskor nem kell adatot másolni, csak pointert és hosszt állít rá a fordító.
- fenti példánál ha max-nál rövidebb "a" vagy "b" adatvektor, lazán beleolvas a másik részbe (information leakage) vagy beleír a másik részbe (code injection, nem várt végtelen ciklus, bármi). Rust: hibát dob túlolvas/túlírásra.
- C-nél adatcsatornában jön a NULL pointer is vissza. Pici figyelmetlenség és kész a biztonsági rés. Rust: if let Some(a) = akarmi(x,y) { ... }
- C fájlokon keresztül hurcolt globális változók: átláthatatlanság melegágya. Rust: csak unsafe {} módon férhetsz hozzá globális változóhoz.
- szálak (thread): konkurens vektorhasználat: Rust ownership
- free utáni vektorhasználat: Rust ownership & lifetime alapú automatikus memória felszabadítás
- C: alapból újraírható változók, "const" a függvényeknél lustaságból elmarad. Rust: alapból nem újraírható változók. Az újraírhatósághoz "mut" kulcsszó kell. Indokolatlan "mut" warningot ad.
- fegyelem netovábbja: double és float között nem tudsz műveletet végezni. Explicit mond meg, hogy melyiket alakítsa át a másikára. C-ben okozott nekem már ez az automatizmus is félreszámolást.
- ...
Visszatekintve a C tényleg olyan, mint biztonsági öv nélkül versenyautót vezetni. Szabadság, szerelem. Továbbá átlagosan 1,2-szeres tempó, de nagyobb eséllyel kompromittálható szoftver.
Lásd még:
- Microsoft: Checked-C (csak részben ad megoldást)
- Microsoft: Verona projekt (Rust alapon, elején tartanak)
- A hozzászóláshoz be kell jelentkezni
Direkt C szintaxisú nyelvet írtam, nem C-t, ez ugyanis az összes (általam ismert) C szintaxisú nyelvben probléma. A Rustot ugyan nem ismerem, de ahogy nézem nem sok köze van a C szintaxishoz; az nem C szintaxis, hogy kapcsos zárójeleket használunk blokkindikátornak.
- Ez valóban gáz a C-ben, de ezt más nyelvek is megoldották, pl. Pascal.
- Dettó, ez a tömbök manuális memóriakezelésének eredménye; ahol ezt a nyelv intézi, ott működik.
- A nullpointereket minden nyelvben le kell kezelni, ahol vannak. Ezért kár kárhoztatni a C-t. (Mondjuk Java-ban vicces, hogy nullpointer nincs, de exception van rá...)
- Ez az unsafe ez tök jó dolog. Kulcs a lábtörlő alatt. :) Ha tényleg preventálni akarom, akkor megtiltom, ha meg nem, akkor meg engedem. Ez így egy felesleges rituálé.
- A data-lockot, vagy a data-isolationt bármilyen nyelvben meg lehet csinálni. Akár C-ben is. Direkt persze meg lehet kerülni, de azt is ugyanúgy minden nyelvben lehet.
- Ezt is megoldotta sok más nyelv.
- Dettó.
- Pascal kódot kell írni C-ben és castolni a két típus között. :P Egyébként ezt a nyelvnek automatikusan tudnia kéne, hogy gépi kód szinten két eltérő méretű változó közti műveletvégzés esetén a kisebbre mindig rá kell húzni egy extendet. Aztán ha a végeredmény is a kisebb adattípusban van, akkor utána meg egy shrinket. Persze force-olni lehet már előtte, hogy a nagyobbat shrinkelje, de akkor meg azonos méretek közt végzünk műveletet.
Az 1.2-szeres tempó azért elég nagy alulbecslés. A kompromittálhatóság stimmel, de kikerülhető, ha odafigyel az ember.
- A hozzászóláshoz be kell jelentkezni
Az 1.2-es Rust-C tempóarány a C javára általános esetre az én eddigi tapasztalatom. Ehhez mérten kezeld, érdemes utánamérned.
Vannak komolyabb tesztek meglepő eredménnyel: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/rus…
"ha odafigyel az ember" --> tapasztalat azt mutatja, hogy van szép számmal, amikor ez nem teljesül és ez igen sok sérülékenység forrása.
- A hozzászóláshoz be kell jelentkezni
Én általánosságban beszéltem, hogy az 1.2 az nagyon alulbecsült, nem a Rustról, hiszen azt nem is ismerem.
Tény, de ez minden nyelvben így van, maximum nincs akkora impact. Unsafe kódot bármiben lehet írni.
- A hozzászóláshoz be kell jelentkezni
> - A nullpointereket minden nyelvben le kell kezelni, ahol vannak.
Igen. Kérdés, hogy ha elfelejted, a fordító szól-e.
> - Ez az unsafe ez tök jó dolog. Kulcs a lábtörlő alatt. :) Ha tényleg preventálni akarom, akkor megtiltom, ha meg nem, akkor meg engedem. Ez így egy felesleges rituálé.
Nem. Nyilván van rés, hiszen másképp nem lehetne drivert írni, vagy 1-2 alacsonyszintű dolgot (pl. hatékony adatszerkezetek). De legyen az a szabály, hogy „alkalmazásba nem írunk unsafe-et”. És ez meg is oldható. Nehezebb persze safe Rust kódot írni, de hát valamit valamiért.
Másrészről még az unsafe blokkokat le is lehet (és érdemes) korlátozni minimális méretűre, és azt sokkal könnyebb körbetesztelni. Az összes többire ott vannak a nyelvi garanciák. (Nem azt mondom ezzel, hogy nem kell tesztelni azt, hogy a program a specifikáció szerint viselkedik-e).
> - A data-lockot, vagy a data-isolationt bármilyen nyelvben meg lehet csinálni. Akár C-ben is.
Megintcsak az a helyzet, hogy a Rust elvárja, hogy a szálak közt megosztott adat vagy csak olvasható legyen, vagy atomi típus, vagy lock mögé kerüljön. Nem tudsz versenyhelyzetet csinálni. C-ben csak a lehetőségünk van meg, hogy lock-oljunk. Ha elfelejtjük, az undefined behaviour. Gyakran átesik a teszteken, piszok nehezen reprodukálható, következményét tekintve pedig egy segfault a szerencsésebb esetek közé tartozik, mert nyugodtan össze is firkálhatja a memóriát, és adatvesztést okozhat.
> > - free utáni vektorhasználat: Rust ownership & lifetime alapú automatikus memória felszabadítás
> - Ezt is megoldotta sok más nyelv.
A felszabadítást igen, a referenciák (ha vannak raw referenciák) lifetime-ellenőrzését nemigen. Szintén undefined behaviour-t szűrünk ki ezzel, ráadásul olyat, ami a jelenlegi bugok elég nagy részét képezik.
- A hozzászóláshoz be kell jelentkezni
> Igen. Kérdés, hogy ha elfelejted, a fordító szól-e.
Annak a nyelvhez nincs köze, az a fordító függvénye.
> De legyen az a szabály, hogy „alkalmazásba nem írunk unsafe-et”.
Igen, így kezdődik az ideologizálás. Ennyi erővel C-ben is lehet "szabályokat" hozni.
> Megintcsak az a helyzet, hogy a Rust elvárja, hogy a szálak közt megosztott adat vagy csak olvasható legyen, vagy atomi típus, vagy lock mögé kerüljön.
Pointer Rustban is van. Mint fentebb kiderült, unsafe mód is van. Innentől kezdve a fordítónak már komoly heurisztikát kéne végeznie fordításkor, hogy rájöjjön, hogy egy elméletileg csak olvasható cross-thread adat címét én bedobtam egy pointerbe és mivel a processz által allokált területén van, így memory-access szinten férek hozzá, megkerülvén a runtime védelmi mechanizmusait. Nyilván ez nem a Rust hibája, hanem a hülye programozóé, aki ilyet csinál, de 100%-ig hülyebiztos rendszer nincs. És itt megint előállt, hogy vagy engedem, vagy tiltom, a kettő keveréke nem létezik, az az engedem, de szívatom a felhasználót kategória.
> C-ben csak a lehetőségünk van meg, hogy lock-oljunk. Ha elfelejtjük, az undefined behaviour.
Ez nem mond ellent annak, amit mondtam. A C a lehetőségek nyelve. Az öntökönlövésre is, de másra is.
> Gyakran átesik a teszteken, piszok nehezen reprodukálható, következményét tekintve pedig egy segfault a szerencsésebb esetek közé tartozik, mert nyugodtan össze is firkálhatja a memóriát, és adatvesztést okozhat.
Ez így van, de unsafe és/vagy rossz kódot bármilyen nyelven lehet írni.
> A felszabadítást igen, a referenciák (ha vannak raw referenciák) lifetime-ellenőrzését nemigen. Szintén undefined behaviour-t szűrünk ki ezzel, ráadásul olyat, ami a jelenlegi bugok elég nagy részét képezik.
Ez implementáció kérdése. Le lehet implementálni C-ben és egyéb nyelvekben is. A Rust akkor ezt itt default runtime szinten támogatja, ennyi a különbség.
- A hozzászóláshoz be kell jelentkezni
> Igen. Kérdés, hogy ha elfelejted, a fordító szól-e.
> > Annak a nyelvhez nincs köze, az a fordító függvénye.
Van, ami a fordító függvénye, és van, amihez nyelvi elem kell. Optional típus pl. nincs a C-ben, C++-ban (stl) már van. Enélkül, vagy ilyesmi nélkül fordítási időben nem derül ki, hogy kiolvashatok-e egy pointert, vagy érvénytelen.
> > De legyen az a szabály, hogy „alkalmazásba nem írunk unsafe-et”.
> Igen, így kezdődik az ideologizálás. Ennyi erővel C-ben is lehet "szabályokat" hozni.
Ez nem ugyanolyan, mint pl. a „minden pointert ellenőrizzünk, hogy NULL-e”.
Ez egy egyszerű szabály, és még egyszer: alkalmazást lehet írni safe (alapértelmezett) módban. Driver-re meg nincs az a programnyelv, ami felelősséget tudna vállalni pl. azért, hogy melyik memóriacímre milyen regiszter van map-elve. Szóval elkerülhetetlen az unsafe, mint nyelvi elem - alkalmazásfejlesztésnél meg tökéletesen elkerülhető.
Amúgy safe módban nem tudsz pointert dereferálni. Anélkül meg ugye nem sok értelme van pointert használni. Tehát úgyis mindenhova referenciát teszünk, ahol raw hivatkozás kell. A referenciákra pedig semmi engedményt nem tesz az unsafe (talán a pointer derefen kívül nincs is más hatása...). Szóval ritka, hogy véletlenül becsúszik egy unsafe. Általában csak komolyabb refaktorálással tudnád elrontani a programot, lényegében azt már akarni kell.
Más kérdés, hogy volt már bukta abból, hogy programot a kezdetektől unsafe blokkokkal írtak tele. Ez nyilván nem a nyelv hibája.
> > C-ben csak a lehetőségünk van meg, hogy lock-oljunk. Ha elfelejtjük, az undefined behaviour.
> Ez nem mond ellent annak, amit mondtam. A C a lehetőségek nyelve. Az öntökönlövésre is, de másra is.
Ez nem mond ellent annak, amit mondtam. A Rust is a lehetőségek nyelve. Az öntökönlövésre kevésbé, másra inkább. :)
> > A felszabadítást igen, a referenciák (ha vannak raw referenciák) lifetime-ellenőrzését nemigen. Szintén undefined behaviour-t szűrünk ki ezzel, ráadásul olyat, ami a jelenlegi bugok elég nagy részét képezik.
> Ez implementáció kérdése. Le lehet implementálni C-ben és egyéb nyelvekben is. A Rust akkor ezt itt default runtime szinten támogatja, ennyi a különbség.
- C-ben nem lehet implementálni pl. shared pointert, mert nincs destruktor. (Állítólag GC lib létezik, most nem nézek utána, de tutira veszem, hogy nem teljesen automata).
- De azért hangsúlyoztam, hogy raw referenciák, mert nem smartpointerről beszélek (futásidejű mechanizmusokkal (bár olyan is van) ), hanem fordítási idejű ellenőrzésről, ehhez pedig kell a nyelv támogatása. Sok esetben külön magyarázat nélkül is látja, hogy mit engedhet meg, de vannak kivételek, ilyenkor magyarázni kell neki, különben túl szigorú, mert hibát nem engedhet meg. Hát pl. az ilyenek miatt nehezebb kicsit belejönni. De bele lehet. :)
- A hozzászóláshoz be kell jelentkezni
> Optional típus pl. nincs a C-ben, C++-ban (stl) már van. Enélkül, vagy ilyesmi nélkül fordítási időben nem derül ki, hogy kiolvashatok-e egy pointert, vagy érvénytelen.
Lehet, de megkerülni azt is meg lehet.
> Ez egy egyszerű szabály, és még egyszer: alkalmazást lehet írni safe (alapértelmezett) módban. Driver-re meg nincs az a programnyelv, ami felelősséget tudna vállalni pl. azért, hogy melyik memóriacímre milyen regiszter van map-elve. Szóval elkerülhetetlen az unsafe, mint nyelvi elem - alkalmazásfejlesztésnél meg tökéletesen elkerülhető.
Nem regiszterekre gondoltam, egy egyszerű allokált terület túlcímzésére pl. olyan pedig alkalmazásfejlesztésnél is előfordul, nem csak C nyelvben.
> Amúgy safe módban nem tudsz pointert dereferálni. Anélkül meg ugye nem sok értelme van pointert használni. Tehát úgyis mindenhova referenciát teszünk, ahol raw hivatkozás kell. A referenciákra pedig semmi engedményt nem tesz az unsafe (talán a pointer derefen kívül nincs is más hatása...). Szóval ritka, hogy véletlenül becsúszik egy unsafe. Általában csak komolyabb refaktorálással tudnád elrontani a programot, lényegében azt már akarni kell.
> Más kérdés, hogy volt már bukta abból, hogy programot a kezdetektől unsafe blokkokkal írtak tele. Ez nyilván nem a nyelv hibája.
Dehát le is írtam, hogy ez nem a Rust hibája, hanem a hülye programozóé. És éppen ez volt a lényeg, hogy ha a programozó hülye, akkor unsafe és pointer és ugyanott vagyunk, mint C-nél, have a segfault. A hülyeség ellen semmi sem véd.
> Ez nem mond ellent annak, amit mondtam. A Rust is a lehetőségek nyelve. Az öntökönlövésre kevésbé, másra inkább. :)
Akkor ez a szál kétirányú zsákutca. :P
> C-ben nem lehet implementálni pl. shared pointert, mert nincs destruktor. (Állítólag GC lib létezik, most nem nézek utána, de tutira veszem, hogy nem teljesen automata).
C-ben minden pointer "shared", hiszen a process a saját címterében oda nyúlkál, ahova akar.
> - De azért hangsúlyoztam, hogy raw referenciák, mert nem smartpointerről beszélek (futásidejű mechanizmusokkal (bár olyan is van) ), hanem fordítási idejű ellenőrzésről, ehhez pedig kell a nyelv támogatása. Sok esetben külön magyarázat nélkül is látja, hogy mit engedhet meg, de vannak kivételek, ilyenkor magyarázni kell neki, különben túl szigorú, mert hibát nem engedhet meg. Hát pl. az ilyenek miatt nehezebb kicsit belejönni. De bele lehet. :)
A fentebbi példához már kőkemény heurisztika kéne. 100%-os védelem nincs.
- A hozzászóláshoz be kell jelentkezni
Lassan pontot teszek ennek a szálnak a végére. :)
> > Optional típus pl. nincs a C-ben, C++-ban (stl) már van. Enélkül, vagy ilyesmi nélkül fordítási időben nem derül ki, hogy kiolvashatok-e egy pointert, vagy érvénytelen.
> Lehet, de megkerülni azt is meg lehet.
Miről is vitázunk ebben a pontban? hg2ecz írta:
- C-nél adatcsatornában jön a NULL pointer is vissza. Pici figyelmetlenség és kész a biztonsági rés. Rust: if let Some(a) = akarmi(x,y) { ... }
azaz a Rust kivédi. Fordításkor, típusosság alapján, mivel az Option<T> nem kompatibilis a T-vel. Nem tudom, mire gondoltál, hogy megkerülni hogyan lehet. Ezt egy kósza unsafe kulcsszóval sem tudod megkerülni, csak ha refaktorálod a kódot, és mindenhol átírod a referenciákat pointerekre, meg ami még ezzel jár. De ezt már nagyon kell akarni. A lényeg az, hogy a könnyen elkövethető, nehezen debugolható, akár adatvesztést is okozó problémákat ki tudjuk szűrni.
> Nem regiszterekre gondoltam, egy egyszerű allokált terület túlcímzésére pl. olyan pedig alkalmazásfejlesztésnél is előfordul, nem csak C nyelvben.
Ezért van Rustban bounds checking.
> ha a programozó hülye, akkor unsafe és pointer és ugyanott vagyunk, mint C-nél, have a segfault.
Könnyű mondani, hogy „a programozó hülye”, de nem. Nem mindegy, hogy nehezen észrevehető hibáról beszélünk, vagy fordítva: nehezen elkövethetőkről. Mégegyszer: a statisztikák szerint a bugok nagy része memóriakezelési hiba. A nehezen észrevehető.
> C-ben minden pointer "shared", hiszen a process a saját címterében oda nyúlkál, ahova akar.
Kommunikációs elcsúszást érzékelek. Hol runtime automata felszabadításról beszélünk, hol statikus (compile time) lifetime-ellenőrzésről.
C-ben egyébként minden pointer shared az adat elérésére (bár inkább az adatra szokták ilyenkor mondani, hogy „shared”), és egyik sem rendelkezik shared ownership-pel. Shared pointer alatt leggyakrabban az utóbbit értjük.
> A fentebbi példához már kőkemény heurisztika kéne. 100%-os védelem nincs.
Igen, lassú is a fordító. De ezekre az esetekre is van 100%-os védelem. Még egyszer: ahol kell annotálni, és nem teszem, ott max. compile error történhet, hibás kód generálása nem.
- A hozzászóláshoz be kell jelentkezni
Itt az első részben leírod, hogy kivédi a Rust, aztán meg leírod, hogy igazából meg lehet kerülni, csak nagyon akarni kell. Miről akarsz itt most akkor meggyőzni, amikor én ugyanezt mondtam? :)
> Ezért van Rustban bounds checking.
Na ja, de ez meg más nyelvekben is van. C-ben nincs.
> Könnyű mondani, hogy „a programozó hülye”, de nem. Nem mindegy, hogy nehezen észrevehető hibáról beszélünk, vagy fordítva: nehezen elkövethetőkről. Mégegyszer: a statisztikák szerint a bugok nagy része memóriakezelési hiba. A nehezen észrevehető.
És ezeknek a hibáknak a managelt memóriakezelés a C-nél fejlettebb nyelvekben (C++, Pascal, whatever) meg is akadályozza. (A "hülye programozó" kitétel meg nem azokra vonatkozott, akik véletlenül memóriahibára futottak, hanem aki a fenti példában leírt marhaságot elköveti.)
> C-ben egyébként minden pointer shared az adat elérésére
Esküdni mernék, hogy ezt írtam én is...
> (bár inkább az adatra szokták ilyenkor mondani, hogy „shared”)
Esküdni mernék, hogy én is idézőjelbe raktam...
> és egyik sem rendelkezik shared ownership-pel.
Esküdni mernék, hogy nem is állítottam ilyet...
> Shared pointer alatt leggyakrabban az utóbbit értjük.
Hát, hogy a Rust-os terminológia mit ért alatta, azt én nem tudom. Én csak értelmeztem a szavakat.
> Igen, lassú is a fordító. De ezekre az esetekre is van 100%-os védelem. Még egyszer: ahol kell annotálni, és nem teszem, ott max. compile error történhet, hibás kód generálása nem.
Hát ehhez képest az elején azzal nyitottál, hogy ha nagyon akarja az ember, akkor megkerüli, akkor pedig nem 100%-os a védelem.
- A hozzászóláshoz be kell jelentkezni
Azért az unsafe {} kulcsszó sem varázsolja C-vé a Rust-ot, így is gyakran többet kell küzdeni a "normális" út helyett a csibészségért.
Az alábbi viszont egyértelműen előny:
$ grep -R -B2 unsafe ./
És nézzük át tüzetesen, hogy az ALKOTÓ az így kidobott helyeken indokoltan nyúlt-e a mágikus kulcsszóhoz.
- A hozzászóláshoz be kell jelentkezni
> Azért az unsafe {} kulcsszó sem varázsolja C-vé a Rust-ot
Ilyet senki nem is mondott.
- A hozzászóláshoz be kell jelentkezni
"Visszatekintve a C tényleg olyan, mint biztonsági öv nélkül versenyautót vezetni." Az emberek egy bérelt elektromos autóval képesek bekapcsolt biztonsági öv mellett a villamos síneken is menni
Az általad felsoroltak nem nyelvi problémák, hanem egy tervezési/fejlesztési/programozói bakigyüjtemény. Az hogy egy nyelvben valamit megtehetsz, az nem azt jelenti hogy meg kell tenned.
A Rust csak rákényszerít arra, hogy ne tudj hülyeséget csinálni tudatlanságból/figyelmetlenségből
// Happy debugging, suckers
#define true (rand() > 10)
- A hozzászóláshoz be kell jelentkezni
Teljesen áttekinthetetlenné tudja tenni a kódot.
Az, hogy nem kell kitenned a kapcsoszárójeleket? Hogyan teszi ez áttekinthetetlenné? Nem igazán értem.
Számtalan hibalehetőség forrása
Szerintem ez addig volt igaz, amíg nem volt -Wmisleading-indentation. Vagy tudsz olyan esetet mutatni, amit gyakran el lehet rontani, és nem fogja meg ez a warning?
- A hozzászóláshoz be kell jelentkezni
Szerintem ez addig volt igaz, amíg nem volt -Wmisleading-indentation. Vagy tudsz olyan esetet mutatni, amit gyakran el lehet rontani, és nem fogja meg ez a warning?
Meg tudod mondani, hogy iccarm -nál vagy Cosmics -nál melyik kapcsoló adja ugyan ezt a működést? Van ám élet a GCC/CLANG világán túl is ;)
- A hozzászóláshoz be kell jelentkezni
Hát, valszeg a mindenféle lint progikban is lehet ilyesmi funkció, nem tűnik olyan nagy dolognak. Meg az is elképzelhető, hogy nem olyan nagy melóval megoldható, hogy leforduljanak ezek az embedded kódok gcc-vel is.
- A hozzászóláshoz be kell jelentkezni
Ebben egyet értünk, csak mintha azt mondtad volna, hogy ezeket a dolgokat a fordító manapság megoldja. Erre reflektáltam, hogy attól függ :) Professzionális környezetben nem hiszem, hogy bármilyen programozási nyelven dolgoznak CC szabályok, illetve az ezeket kikényszerítő static analyzerek nélkül.
- A hozzászóláshoz be kell jelentkezni
Ha tiszta kódot akarsz, akkor használj mbeddr-t! Nekem nem volt türelmem hozzá, de tény hogy magán az AST-n dolgozni és a részfeladatokra megfelelő DSL-eket alkalmazni / írni igazi felüdülés a spagetti kódok után. Ha persze megfizetnék, akkor szívesen dolgoznék olyan cégnek, aki alkalmazza, de nálunk általában a "csak működjön" a cél sajnos.
- A hozzászóláshoz be kell jelentkezni
A programod által include-olt header fájlok jó eséllyel használják ezt a stílust makrókban, illetve inline függvények definíciójában. Tehát ha lenne ilyen opció, hasalna a fordításod, vagy pragmázni kéne agyba-főbe hogy a te hatáskörödön kívüli include fájlokra kapcsold ki ezt az ellenőrzést.
- A hozzászóláshoz be kell jelentkezni
Ez már megint... mintha a kódokban ez lenne a legnagyobb probléma.
Millió dolgot lehetne csinálni a C-vel, de NEM ezek a problémái. Az integer meg a float osztás összekeverése sokkal szemetebb dolog pl.
Ettől még ez a szabvány. Ha nem tetszik, használj kód formattert, ha nincs, akkor írj egyet. Nyitó {-t pedig csak függvényekkel szokás külön sorba tenni, legalábbis ott, ahonnan én jövök. De a whitespace-nek épp az a lényege, hogy ne vesszünk rajta össze.
- A hozzászóláshoz be kell jelentkezni
Ha nem csak a programot nézed, hanem projekt szinten gondolkodol, akkor a karbantarthatóság lesz az egyik legfontosabb tényező. Ennek pedig fontos eleme a kód olvashatósága, és így a formázás. Természetesen nem a whitespace helyétől fog a program jól működni, de ettől még fontos. Ugyanakkor minden erre szánt másodperc "pénzkidobás" ha csak a fejlesztés fő célját, a következő helyesen működő rilízt nézed. Ezért, próbáljuk ezeket a dolgokat automatizálni amennyire lehet, (meg azért, mert mechanikus és unalmas munka). Az a baj, hogy ha a nyelvnek nem része a formázás, akkor az automatizálásnak lesznek korlátai, mint ahogy a C -nél vannak is (pl. egy projektben több már létező komponenst használni).
A C és a C++ filozófiája, hogy a fejlesztő okos, és tudja mit csinál, ezért a nyelv nem próbál megvédeni önmagadtól. Sajnos ez a szemlélet akadályozza a skálázódást, sokkal több programozó kellene mint amennyi rendelkezésre áll. Így azokon a területeken, ahol a teljesítmény nem elsődleges fontosságú, "biztonságosabb" nyelveket használnak. Sajnos a C és más nyelvek közötti átjárhatóság ugyan abba a skálázódási problémába ütközik amit fent említettem, hiszen újra spéci tudású embereket igényel, akik 2 vagy több nyelven is profik. Ezért aztán "hagyománya" van annak, hogy bizonyos területeken milyen nyelven programozunk. Pl firmwaret vagy rendszer programot általában C -ben írunk, pedig egyes részeken más lehet hogy előnyösebb lenne. Így aztán végezetül marad a "tákolás", azaz, hogy egyéb eszközökkel próbáljuk a kód minőségét védeni. Vannak próbálkozások a helyzet javítására, mint pl. a Rust vagy a mbedder de az emberi tényező miatt, ezek nehezen kapnak lendületet.
- A hozzászóláshoz be kell jelentkezni
Bocsi, de ez bullshit. Tudom hogy ezt nyomatják mindenhol, coding guidelines meg az összes barom formai követelmény.
Nem csak programnyelvekben, máshol is. Igen ritka az a hely, ahol annyi ember dolgozna C kódokon egyszerre, hogy ez tényleg segítene.
A gyakorlat az, hogy valaki megcsinálja, aztán vakarjuk a fejünket, ha másnak át kell venni. Sokszor újraírni.
De az alapprobléma nem a kód formázás, hanem hogy analfabéták programoznak. Nem véletlen létezett régen egy programozó matematikus képés. Azok még tudták hogy működik a nyelv meg a gép, a maiak meg összeollózni (vagy azt sem) tudnak a github-ról meg a stackoverflow-ról. Magam is a fiatalabb korosztályba tartozom, de borzasztó látni, hogy mi megy körülöttem.
Erre a minőségisek bevezetik az ilyen tegyük ki a zárójeleket baromságokat, erre felvesznek még három embert aki ezt le is ellenőrzi, és egy dekával nem lesz tőle jobb a kód. Viszont ezt könnyű ellenőrizni, és auditkor lehet villogni, hogy nekünk milyen szuper fejlesztési folyamatunk van, csak mögötte semmi valós tartalom nincs.
- A hozzászóláshoz be kell jelentkezni
Na de akkor ki irja a githubon es SO-n levo kodokat? :)
- A hozzászóláshoz be kell jelentkezni
A helyzet az, hogy programozni bonyolult, és semmiféle absztrakció/design/whatever nem változtat ezen. Sokszor egyszerűbb újra írni a dolgokat, mint megérteni mit akart a szerző, illetve miért úgy csinálta meg a programot ahogy. Ránézésre kevesebb kockázat is, hiszen az olvasgatás és dokumentálás helyett "érdemi munka", programozás zajlik. Kódot olvasgatni/dokumentálni lehet hetekig, aztán a végén mégis csak újraírás lesz a verdikt. Könnyebb eladni a főnöknek az újraírást :)
Nagyon kevés helyen dolgoznak egyszemélyes, szuper programozókból álló csapatok 1000 évig ugyan azon a programon. Ha pedig a developerek változnak, meg kell küzdeni az emberek közötti információ mozgatás problémájával. A rendes doksi ritka mint a fehér holló, illetve a "forrás a dokumentáció". Akkor viszont legalább legyen olvasható, nem?
Nézhetjük úgy is, hogy a coding-style az utánad jövő munkájába történő befektetés. Hogy megterül e? Ki tudja, de ha nem túl drága, hülyeség lenne kihagyni. Automatizálás ugyebár :)
Megint másként megfogalmazva, helyesen illetve olvastatóan írni is hülyeség mindaddig amíg csak te olvasod el. Ha viszont másnak kell utánad boldogulni, akkor a kérdés nem olyan egyszerű.
- A hozzászóláshoz be kell jelentkezni
Ezzel amit írtál, egyet is tudok érteni, oké.
A kérdés inkább az, ha már rászánjuk magunkat holmi „coding style” követésére, az milyen legyen.
Ami engem illet, én kialakítottam a magam számára egyet, ami szerintem sokkal jobb mint az amiket a fejemhez szoktak vágni hogy követnem kéne, hogy például a kapcsos zárójelek egymás alá kerüljenek, meg ilyesmi, ugyanis én nem efféle főként merőben külalaki dolgokból indultam ki. A legfőbb elveim a következők voltak:
—bizonyított tény, hogy egy program általában akkor jó, ha a részei „gyengén kapcsoltak”, azaz a felelősségi körök világosak.
—Ez elsősorban azáltal ámogatható, ha egy függvény (netán szubrutin) csak EGYETLEN dolgot csinál (de azt jól). Már Murphy is megmondta ugye, hogy többféle célra is alkalmas konyhagép egyetlen funkciót se lát el tisztességesen...
—A függvények tehát rövidek kell legyenek. Ökölszabályként kimondható, ha a függvény nem fér rá egyetlen képernyőoldalra, még úgy se ha ezen oldal sorai sűrűn teleírtak, akkor épp ideje elgondolkodni azon, miként lehetne azt a függvényt több részre szétbontani...
—Ha mégis ilyen hosszú függvényt írunk, legalább a benne szereplő ciklusok illetve switch-ek férjenek ki egy-egy képernyőoldalra.
—Ha még a switch-ek se, legalább a case-ágaik.
És így tovább.
Szóval, ebből indultam ki. Na most ha ezt én igyekszem betartani (márpedig igyekszem, óriási erőkkel, s általában sikeresen!) akkor elérhető, hogy mindig amikor egy bizonyos részen dolgozom, az adott „taszk” (általában egy teljes függvény, de legalábbis az adott ciklus, vagy switch, stb) teljes egészében látható a képernyőmön. És ez nagyon jó, mert szuperul áttekinthető minden, egyetlen pillantással, nem kell hozzá görgetnem se... Nálam a tömbök szoktak rém hosszúak lenni, mert általában ugrótáblák. De azt ki bánja...
Néha előfordul hogy nálam se fér be minden egy képernyőoldalba, kicsit kilóg belőle. Nem nagyon, de kicsit. Ez rém zavaró, rontja az áttekinthetőséget. Ilyenkor bizony az van, hogy igyekszem spórolni a hellyel, tehát úgy tördelek hogy mégis beleférjen. Mert az mindennél fontosabb hogy egyetlen pillantással átlássam a teljes izémizét amin épp dolgozom! Ennek érdekében szoktam rá, hogy például nem hagyok szóközt a for és a nyitózárójel közt. Meg hogy nem így írom:
int
myfunc (char **valami)
{
hanem így:
int myfunc(char **valami){
Nálam ez vált be. Ez, hogy a program eleve akkora szeletkékből áll, amik könnyen áttekinthetőek külön-külön.
Ismétlem nem okvetlenül egy teljes függvény, bár többnyire még az is összejön. De ha mégse, akkor a függvény valami bizonyos értelemben egységnek tekinthető része. A tördelés ennek van alárendelve. Ez nálam remekül bevált. Én így nézem ezt a kérdést, ebből az aspektusból. Lehet hogy valakinek ez nem tetszik majd, és én el is fogadom hogy lehetnek olyan körülmények amikor nem ez a legszerencsésebb döntés, de tiltakozom azellen hogy itt egyesek megpróbálják úgy feltüntetni az én módszeremet hogy én csak ész nélkül írom a kódot, mindenféle átgondolás nélkül, fittyet hányva a formázásra és a „formára”!
Egyáltalán nem!
Az én tördelésemben igenis van egy sajátos logika, amit ráadásul nem ad-hoc módon alkalmazok hanem igen szigorú következetességgel.
Jellemzően az egyes részek amik ki kell férjenek egyetlen képernyőre, egymástól a kódban többnyire igen jól láthatóan el is vannak választva többsoros kommentsorokkal, így rögvest pompásan látható az is, meddig érdemes legörgetni a képernyőt hogy az adott részt lássuk a képernyőn a maga teljességében...
- A hozzászóláshoz be kell jelentkezni
Igen, erre írtam fentebb/lentebb, hogy a téma 2 részre oszlik. Coding stlye (hol legyen a space), ez automatizálható, és ide kapcsolódik a topik nyitó kérdése. A másik a coding-practices, avagy "hogyan programozzunk jól". Ez már nehezebben automatizálható, főleg az általad említett magasabb szintű témakörök. Ezt próbálja megoldani pl. a "cyclomatic complexity" mérőszám, de minél elvontabb, design jellegű dolgok felé megyünk, annál kevésbé automatizálható lesz a dolog. Ezt a részt nem igazán lehet ész nélkül tolni.
Ami a saját coding style -t illeti, nekem is volt sajátom. Ugyanakkor mivel senki sem fogja átvenni, végső soron pont a lényeg, a konzisztencia vész el. Nem véletlen, hogy a nagyobb projektek valamelyik meglévő elterjedt stílus mögé állnak be. Linuxos környezetben nehezen elfogadtatható, ha nem a Linux coding styile -t, vagy annak kissé módosított változatát használod.
Végső soron a programozónak tudnia kell bármilyen kódot olvasni. Ami igazan zavaró az az összevisszaság.
- A hozzászóláshoz be kell jelentkezni
És ne is warningoljon, hanem ha nincs ott, akkor simán ERROR és kész.
Ajánlom a gcc -Werror flag-ét.
- A hozzászóláshoz be kell jelentkezni
https://clang.llvm.org/extra/clang-tidy/checks/readability-braces-aroun…
Hatrany: clang-tidy kell, szoval nem a fordito oldja meg neked. Persze git pre-commit hook-kal kombinalva mar okes a helyzet. Ha a junior nem csinalja jol a dolgot, akkor visszadobja a git commit-ot.
Elony: szerintem a clang-tidy ki is tudja javitani a kodformazasi bakikat.
Alapjaban veve ertem a haborgast a temaban. En erre a konkret dologra nem vagyok erzekeny, dehat mindenki masra ugrik. Csak szerintem nem feltetlenul a fordito a forraskod-kinezet-naculas legjobb eszkoze.
- A hozzászóláshoz be kell jelentkezni
működik így is, úgy is... hol a bibi?
-fs-
Az olyan tárgyakat, amik képesek az mc futtatására, munkaeszköznek nevezzük.
- A hozzászóláshoz be kell jelentkezni
Most lusta vagyok vegigolvasni es kiprobalni is, de ket opcio:
-Wno-misleading-indentation
-Werror
Elobbi a szar behuzasnal warningol, asszem ebbe beletartozik az is, ha ezt irod:
if(a<b)
g++; h++;
masik meg minden warningot errorkent kezel. Ezzel nem fogod kikenyszeriteni a {} hasznalatat, de ha valahol ennek ellenere benezed, azt eszreveszed.
A strange game. The only winning move is not to play. How about a nice game of chess?
- A hozzászóláshoz be kell jelentkezni
Csakhogy nekem épp az a fixa ideálom, hogy szeretném kikényszeríteni a kapcsos zárójeleket...
Nekem nem a behúzással vannak gondjaim, sőt, ragaszkodom hozzá hogy abba ne szóljon bele! Én csak azt szeretném ha a felvetett szituációkban ragaszkodna ahhoz hogy oda kellenek azok a zárójelek és punktum.
- A hozzászóláshoz be kell jelentkezni
Nincs mese, írnod kell egy C fordítót C-ben :) - komolyra fordítva: szerintem ha ilyen spéci és kizárólagos igényeid vannak és egyik javasolt megoldás sem megfelelő, mert nem csinálja meg 100%-san azt, és csakis azt(!) amit te szeretnél, akkor miért nem írsz C-ben egy elővizsgáló programot, amit fordítás előtt ráengednél a kódra, és az kidobná egyből a neked nem tetsző dolgokat (amik ráadásul alapvetően nem is mondanak ellent a nyelv szabályainak)? Szerintem az lenne az igazán tökös megoldás - főleg, hogy elmondásod szerint komoly C tudással rendelkezel. Nem is értem, hogy miért nem ezzel a megoldással kezdted?
- A hozzászóláshoz be kell jelentkezni
Ebben neked abszolút igazad van, de annyira, hogy ez a kézenfekvő megoldás nekem is azonnal eszembe jutott. Egyszerűen reménykedtem benne eddig, hogy hátha megúszom ezt a melót. Tudod, lustaság és kényelemszeretet még bennem is van néha, aztán meg sokszor fejemhez vágják errefelé azt is hogy ne akarjam újra feltalálni a kereket, stb...
És tényleg, minek, ha már megvan készen!
Szóval gondoltam rákérdezek, hátha van már erre valami megoldás... De ha nincs, akkor természetesen az az egyetlen járható út amit itt fent leírtál.
Ugyanakkor azonban, ha már ilyesmibe vágom a hackemet azaz bocsánat, fejszémet, akkor nem fogom beérni ilyen kevéssel, és teszek róla hogy kibővíthessem a C nyelvet egypár olyan feature-vel amit hiányolok belőle. Az általam írandó „lexikai elemző” (ha szabad e nevet használni rá, bár nem vagyok benne biztos hogy teljes mértékben jogos) az általam kitalált nyelvi elemeket - ha rájuk bukkan a kódban - kicseréli majd szabványos C forráskód részletekre.
Ez azonban megint olyasmi ami nem egetverően sürgős. Egyelőre jobban érdekel egy saját FORTH implementáció megírása. Elméletileg holnap jön az Amazontól 2 megrendelt szakkönyv is e témában, azokat átbogarászom, meglátom mi az amivel kompatibilis tudok maradni és mi az amivel nem, aztán jön pár hetes semmittevés... látszólag. Valójában azonban ez csak annyi hogy ezalatt nem kódolni fogok hanem komolyan megtervezem azt a nyelvet az alapjaitól. Az lesz az igazán nehéz... Az hogy aztán azt végül le is kódoljam, már majdhogynem gyerekjáték. Annyi programnyelvet írtam szórakozásból az utóbbi talán 5 évben, hogy az ilyesmi már nekem rutinmunka. Most jöhetnek majd a trollok hogy nagyzolok meg dicsekszem, de akkor is így van.
Hanem a megtervezés, na AZ AZ IGAZÁN NEHÉZ! Hajaj!
Holott amikor nekikezdtem programnyelveket írni, eleinte azt hittem, hogy hú, hát az én zsenialitásommal aztán semmi nehézséget nem okozhat kitalálni egy hiperszuper új nyelvet amitől mindenki hasraesik, csak kérdéses képes leszek-e egyedül megalkotni, leprogramozni... Erre kiderül, hogy az utóbbi nem is egy olyan szörnyű nagy szám, csak némi szorgalom kell hozzá. Hanem kitalálni...!
A kitalálás tényleg nehéz, ezt nem gúnyból írom. Azért nehéz, mert gyakran egymásnak gyökeresen ellentmondó szempontoknak kell megfelelni. Aztán meg rengeteg olyan ötletünk lehjet amik mind irtóra tetszenek, és tényleg tök jók is mind külön-külön, de el kell köteleznünk magunkat valamelyik mellett, feláldozva ezáltal a többit, mert nem lehet megcsinálni egyszerre __mindet__. Szóval nekem már rég nem a lekódolás okoz gondot, hanem az ilyesmiken morfondírozás veszi el az időmet, hogy eldöntsem, konkrétan MIT_IS szeretnék megvalósítani.
- A hozzászóláshoz be kell jelentkezni