Sziasztok!
A napokban kénytelen voltam elővenni a C nyelvet, amihez nem sok pozitív élmény fűz (de ez legyen egy blogbejegyzés tartalma :) Leginkább JAVA háttérrel rendelkezem (amihez zömében pozitív élmények fűznek...).
Nem egy hatalmas projektről van szó, akár a default módban is kész lenne egykét nap alatt, de egy JAVA stílusú for ciklus rásakor kénytelen voltam felfigyelni a standardok opciójára a gccben. Csak lábjegyzetként a kód:
for (int i=0; i<VALAMI; i++) {
Nem akkora probléma a for előtt deklarálnom a ciklusváltozót (így a javából ismert működést produkálja szemben a fenti kóddal mondjuk Visual C-ben).
Az valódi kérdésem az, hogy nem igazán találtam vitákat a neten az egyes szabványok előnyéről hátrányáról, illetve melyik ami "hivatalosan" ajánlott új projektekhez. Amennyire láttam az alapértelmezett a gnu90 (standard C gnu kiterjesztésekkel). A c99 illetve gnu99 a másik esélyes versenyző és hogy olvastam a gnu1x a készülőben lévő új standard.
A portolhatóság nem elsődleges szempont, a kód a V4L-t használja, így nem cél, hogy mondjuk Visual C-ben leforduljon. Azt viszont szivesen venném, ha egyszer (a távoli jövőben) a V4L-t portolják BSD-re meg OS X-re ott (a majdnai GCC verzión) működjön.
Fontos lenne például, hogy jelenleg ez gond nélkül lefordul (még egy warning sem jön):
memset(buffer, max_length, ' ');
(A 2. és 3. paraméter meg van cserélve) - Ilyen szavashibák felfedezését elvárnám a fordítótól.
Szóval kíváncsi lennék a véleményekre prok és kontrák...
Hozzászólások
void * memset ( void * ptr, int value, size_t num );
Ez a memset deklarációja. Ha te fordító lennél, erre mit mondanál, amikor az int helyett (valószínűleg) int áll, a size_t (ami gondolom unsigned) helyett meg char? De az implicit konverziókra való warningolást nagyon szépen lehet bekapcsolni, gondolom te is megtaláltad ezt http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
----
Hülye pelikán
Nem akarom, hogy hitvitába torkoljon a téma, de nem, nem olvastam el egy háború-és-béke méretű dokumentumot csupán a hibajelentésekről ;) Mindazonáltal -Wall bent volt.
Emellett ákeresve az "implicit conv" és "type conv" -ra sem találtam meg a megoldást. A -Wconversion is csak előjelre figyelmeztet, a többi téma pedig konstruktorokkal foglalkozik.
Amúgy melyik lenne a titkos kapcsoló ami megoldja?
És a fő témára visszatérve: neked melyik szabvány?
Szerintem - mivel a size_t valami typedef unsigned long lehet - semmi nem oldja meg azt a problémát, hogy a 0-ás karakter egyúttal unsigned int is, az pedig nem implicit konverzió C-ben, hogy unsigned longot csinálok belőle.
Ja, és a '' mindenképpen warningot generál -Wall-nál, mert üres karakter nincs a C-ben (error: empty character constant).
Most látom, hogy egy space is volt a két aposztróf között, ezért nem kaptál warningot...
Ha rám hallgatsz - ha már C-t használsz -, a standard C-t használod, gnu extensionök nélkül. Minimum javasolt opció: -pedantic -Wall -Wextra
Tehát nincs //, mint komment, nincs for (int i = 0..., nincs blokk közepén változódeklaráció, stb.
Ezek nem olyan szintű kényelmi dolgok, amiket ne lehetne elkerülni, cserébe megtanulsz úgy kódolni, hogy később ne legyen belőle szopás, amikor valami véletlen folytán pl. egy másik compilert szeretnél használni, mert 10%-kal gyorsabb kódot generál az adott feladatra, és neked pont az a 10% fog még kelleni.
Szerintem.
A standardok elkötelezettje vagyok kézzel-lábbal, a // mint comment még megoldható valami regex-szel viszont a makrók sem tetszettek neki amit jelenlegi C hátteremmel elég nehezen tudnék debugolni. Ez egy természetétől fogva linux-alapú projekt, úgyhogy nem hiszem, hogy ennyire a C89 felé orientálódnék.
A más fordító kérdése viszont jó ötlet - erre a "performance" részére nem is gondoltam adolognak.
Azért ne higgy el mindent egyből, én a "mindent dekraláljunk előré"-t nem tartom jó dolognak. Lássuk az alábbi példát:
if(ritkanigazfeltetel){
/* ritkan lefuto programag */
int bazinagytomb[65535];
...
} else {
/* gyakran lefuto programag */
...
}
namost ha ez egy rekurzív függvény belsejében van, akkor pont hogy spórol a memóriával, míg a pedantic
int bazinagytomb[65535];
if(ritkanigazfeltetel){
/* ritkan lefuto programag */
...
} else {
/* gyakran lefuto programag */
...
}
kód nemkevés memóriát elpocsékol, ne adj isten még fel is zabálja, ami miatt kilövi az OS.
Szvsz: dekralájunk mindent a blokk elején. (mielőtt elkezdődne a flame, szvsz!)
Igazából az if utáni blokk is scopenyitó, tehát annak az elején is deklarálhatsz teljesen nyugodtan és (C89) szabványosan. Amikor C-vel kellett foglalkoznom, és pont hasonló volt a szituáció (nagy tömb kellett), akkor simán nyitottam egy blokkot a függvény közepén, mert a láthatósági/élettartam szabályok szépek és segítenek jobb kódot írni.
"Just a note: variables in ansi C don't have to be declared at the start of a function but rather at the start of a block."
Idézet innen.
----
Hülye pelikán
Akkor csak félreértés volt, erre gondoltam én is.
Rég cztem már, de a bazinagy tömböket nem dinamikusan kéne foglalni? Pedáns módon lefoglalod (nevesíted) a blokk elején a pointert, aztán a ritkanigazfeltetelben meg malloc, vagy ami kell.
Azert az a 64K -s tomb a stack -en odab.sz!
Jo kis debuggolas lehet belole, hogy attol fuggoen honnan hivod neha megy, neha nem.
Masreszt jo nagy stack kell a proginak a ritkan lefuto kod miatt.
Jo, tudom, csak pelda volt, de azert jo ha megmarad az utokornak, hogy ilyet elvetemult dolog csinalni.
omg, "//" es "for (int i;" az fyi ISO 9899:1999 standard C
--
NetBSD - Simplicity is prerequisite for reliability
Nem akarok védeni senkit, de a C-nek több standardja is van, például 89-ben készült egy, amit a topik indítója is preferált. A legújabb nem mindig a legjobb.
Amúgy offtopik címen nem humoros, hogy C++ szabvány előbb volt mint C? Pedig mindkét nyelvet erősen a szükség szülte és erősen a gyakorlat befolyásolta, aztán mégis Bjarne úgy gondolta.
----
Hülye pelikán
Az első C++ szabvány 98-as és van egy 89-es C szabvány. Akkor most mi volt előbb???
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o
javítva
fogalmam sincs hol olvastam amit írtam, de igazad van.
----
Hülye pelikán
Én C99-et használom, a normális fordítók már mind jól támogatják (az MSVC++ nekem nem számít annak, de amúgy sem kell programoznom Win alá hála az égnek). Emellé ha nagyon tiszta kódot szeretnél, akkor használd ezeket az opciókat (csinálj Makefile-t ha még nincs, abba mentsd el, aztán nem kell rá emlékezned):
-Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -Wno-pointer-sign
FreeBSD-n van egy WARNS make változó, amit 0-6-ig lehet beállítani, ezzel szabályozva a warningok szigorúságát, a legtisztább kódok (WARNS=6) ezekket az opciókkal fordulnak. És ott a -Werror is, hogy ha warning csúszna bele, akkor a programozó szépen javítsa csak ki.
Jah, amúgy amikor más kódjával dolgoztam és a végén a WARNS-t növelve letisztogattam a kódot, akkor sikerült már hibákra bukkannom (pl. unsigned változóra < 0 teszt az if feltételben), szóval megerősíthetem, hogy ez a gyakorlatban tényleg működik és hasznos.
Húha.. :) Köszi az opciókat. Nem igérem, hogy egyszerre kapcsolom be mindet, de jó dolog lenne eljutni egy oylan szintre ahol semmiért nem panaszkodik már :)
nice és egy big thx!
+1
ANSI módra:
gcc -ansi -pedantic -W -Wall -Wextra -Wconversion -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wformat=2 -Wformat-security -fshort-enums -fno-common -O3 -ggdb
Ez elégséges infót dob ki, ha elqrnál vmit.
Illetve Beanie-ébe merge-eld bele :)
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
-O3 es -ggdb egyutt LOL
--
NetBSD - Simplicity is prerequisite for reliability
Ráadásul egymás után írva arra se lehet következtetni, hogy esetleg bentmaradt :)
Gyorsan akar debuggolni :D
----
Hülye pelikán
common typo, de látom értelmi képességed nem ér fel ahhoz az absztrakciós szinthez, hogy a sor végén levő két, egymást kizáró kapcsolótól elvonatkoztass....
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
A szó amit keresel: "elnézést"
[ #FreedomFlotilla ] [ hupexpertize© ]
Talán ha Replaced reakciója nem egy LOL lett volna, akkor megérdemelné az elnézéskérést.
Elvileg az enyim mindent implikál, ha jól tudom. AFAIK, a -pedantic meg csak valami kompozit kapcsoló, ami egyszerre több -W* kapcsolót is jelent. A -ggdb csak akkor, ha debuggolni akarsz, mert lassabb lesz a program és növeli a méretet. És épp emiatt értelmetlen a -O3 optimalizálással együtt használni, ahogy előttem is mondták.
jóvanna, kimásoltam ide, szt ottmaradt. Elmondom lassan: Nem használom egyszerre, csak nem töröltem végig a sort.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
Oks, én csak normális magyarázatot akartam hozzáfűzni a lolozás meg az idiótázás helyett, amit társaink feljebb megeresztettek.
"Nem egy hatalmas projektről van szó, akár a default módban is kész lenne egykét nap alatt, de egy JAVA stílusú for ciklus rásakor kénytelen voltam felfigyelni a standardok opciójára a gccben. Csak lábjegyzetként a kód:
for (int i=0; i?VALAMI; i++) {"
ez a C99 standard resze, minden c99 szabvanyt implementalo fordito tudni fogja (viszont visual studio nem ilyen). nem is kezdenek masban kodot, mint c99, ha nem muszaj.
c99-rol itt: http://www.kuro5hin.org/story/2001/2/23/194544/139
"ha egyszer (a távoli jövőben) a V4L-t portolják BSD-re meg OS X-re ott (a majdnai GCC verzión) működjön."
fyi evek ota van: http://netbsd.gw.com/cgi-bin/man-cgi?video++NetBSD-current
tovabba solarison es openbsd-n is.
--
NetBSD - Simplicity is prerequisite for reliability
"ez a C99 standard resze, minden c99 szabvanyt implementalo fordito tudni fogja (viszont visual studio nem ilyen)"
Most direkt kipróbáltam: Visual Studio 2005 (8.0) SP1 simán fordítja. Ez a fordító 5 éves. Felhívnám a figyelmet arra, hogy ( Visual Studio 6.0 != Visual Studio )! Tekintve, hogy azóta kint van 4 újabb verzió, elég csacsi hozzáállás ez. Nem mellékesen: akkor a gcc-t is egy régivel kell azonosítani (pl.: 2.0)?? Mert hát az sem leányálom...
Egyébként jelenleg nincs C99-es fordító a piacon tudtommal, csak az intel. FYI: GCC
MS hivatalos álláspont: Link
És akkor C++0x is:
GCC
VS C++ 2010
--
És hogy ontopic is legyek: Link - tehát a válasz: C89 vagy használj C++-t. :)
--
http://www.naszta.hu
Nekem pl. van olyan 2000-ben telepített linuxom, amin 2.95-ös gcc van. A gép köszöni szépen, jól megy (tűzfal+gateway). :)
hogy nem strict c99-nek megfelelo, az nem lenyeges, alap dolgokat tamogasson:
struct foo a = {
.bar = 1;
}
int n = 10;
char baz[n];
uint32_t num; // stdint.h, legfontosabb, ezt VS is tudja
meg par aprosagot, ami nem jut eszembe :)
--
NetBSD - Simplicity is prerequisite for reliability
Mivel én C++-ozom főleg, ritkán futok bele. :) Én mostanában már az open source-ot is VS alatt csinálom, mert kényelmes és CMake is támogatja. Normálisan dokumentálva van az STL is, és az IntelliSense is jól használható. Megmondom őszintén a nyilt IDE-kből mindig hiányzott valami apróság sajnos. Talán Qt Creator 2-3 verzió múlva... :)
--
http://www.naszta.hu
Nincs ezzel semmi baj, a VC Toolkit 2003 is jól fordítja.
A paraméterek felcseréléséről. A compiler természetesen nem tud minden hibát kiszűrni, ezért ne akard megspórolni a program tesztelését. A tesztelés _minimuma_, hogy minden programsor végrehajtását ellenőrzöd, akkor pedig az ilyen hiba kiderül.
--
CCC3
> A tesztelés _minimuma_, hogy minden programsor végrehajtását ellenőrzöd, akkor pedig az ilyen hiba kiderül.
Te se Magyarországon élsz/dolgozol, ugye?
----
Hülye pelikán
Arra utalsz, hogy úgy adod át a programjaidat, hogy nem próbálod ki egyszer sem?
--
CCC3
Pedig ez teljesen standard eljárás ebben az országban... :)
Arra utalok, hogy itthon a tesztelése a kódnak nem elsődleges szempont. Ahogy látom a te fejedben ez úgy él, hogy neked kiadják, mit csinálj, és te akkor adod át, amikor akarod. Ez még akkor sem így megy, ha saját céged van és saját saját saját, hát még ha alkalmazottként vagy.
----
Hülye pelikán
Úgy látszik, el vagyok maradva.
--
CCC3
Megsugom, ez _sehol_ nincs igy, csak normalis helyen a projvez bekalkulalja a tesztelest is a fejlesztesi idobe, es ugy adja le a projekt hataridejet.
--
És ez hogy jön ide? Nem mondtam, hogy bárhol így lenne, én azt mondtam, hogy mrev szavai végtelen naivitásra utalnak...
----
Hülye pelikán
Szerintem nem tudtad kovetni. Epphogy nem, mert normalis helyen tenyleg vegigtesztelik a program minden egyes sorat, csak normalis helyen ez benne van a hataridoben, mert a projvez a teszteles idejet is bekalkulalja, ami itthon nem divat valamiert.
--
Itt két külön dologról van szó, de nem tudtok elvonatkoztatni.
Mrev azért volt naív az én szememben, mert valahogy sütött róla, hogy szerinte a program akkor van kész, amikor ő úgy gondolja, hogy készen van.
Az is a naivitás, hogy valaki azt feltételezi, Mo-n a normális, alapos tesztelés bevett szokás.
----
Hülye pelikán
En irtam is, hogy ez nalunk valahogy nem divat. Meg nalunk valahogy eleg sok minden nem divat, ami pedig fontos lenne... ezert van ennyi szar program, es valahogy kezdem erteni, hogy az allami megrendelesre keszulo szoftverek mitol olyan pocsek minoseguek, lasd abev.
--
A C99 GCC 4.5.0-tel lassabb lehet nagy számolásigény esetén:
On x86 targets, code containing floating-point calculations may run significantly slower when compiled with GCC 4.5 in strict C99 conformance mode than they did with earlier GCC versions. This is due to stricter standard conformance of the compiler and can be avoided by using the option -fexcess-precision=fast; also see below.
Ha olyan alkalmazást szeretnék írni C-ben ami fut winen és unixon (ural2) is ahhoz mit ajánlanátok?
Root-Tech
akkor strict ansi c-t (c89)
--
NetBSD - Simplicity is prerequisite for reliability
Amiben jolesik. GCC van winre is.
Mondjuk en lehet, hogy c++-ban inditanek, csak legfeljebb nem hasznalnek osztalyokat. Azokon kivul is rengeteg hasznos szolgaltatasa van a nyelvnek.
--
Ezt messzemenőkig tudom támogatni (mindkettő részt, de főleg az utóbbit), a C++ tele van dolgokkal, amelyek egy része átment a C nyelvbe mint kiegészítés, egy kis része még a szabványba is került, de fontos dolgok hiányoznak még mindig. Gondolok itt például a tipusosságra.
----
Hülye pelikán