char * és a printf

 ( muczy | 2006. december 11., hétfő - 11:52 )

#include

char *anyad={"12345"};
int i=0;

int main(){
i=0;
while(1){

if (anyad[i] == '\n'){break;}
printf("%c", anyad[i]);
printf("i: %d\n", i);
i++;

}

i--;
printf("%d\n", i);

return 0;
}

A tömb hosszát kellene megszámolni, string.h nélkül.
Amennyiben gcc3mal fordítom, akkor 13-mat ad, amennyiben gcc4el, úgy 192-t. Erre én azt szoktam mondani, hogy veri incsereszting.
Továbbá win alatt dev-c++-ban megintcsak más eredmény született.

Valaki mondjon legyen szíves valami okosat erre.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

szerintem a string veget nem a \n jelzi, hanem \0

http://www.cs.cf.ac.uk/Dave/C/node7.html

--
http://marvin.elte.hu/ - the astrophysics archive

Na jó, ennyi!
Köszi szépen, bocs a témanyitást...

Gentoo Karvaly

megjegyzesek:
- az "anyad" valtozo egy string-tomb, vagyis a {"12345"} egy char ** tipust implikal es nem char *-ot
- a string ve'ge a 0 karakter ('\0', vagy csak siman 0) es nem a '\n'
- egy kicsit tul van bonyolitva...

char * anyad = "12345";
int    i;
for ( i=0 ; anyad[i] != '\0' ; ) i++;
length=i;

A.

Az eltérés az egyes fordítók között pedig abból adódott, hogy
különbözőképpen ágyazták be a kódba a változót, és volt amelyiknél
több, volt amelyiknél kevesebb NEM_NULLA illetve (nálad: '\n')
karakter pakolódott az után a változód után (ami _nem_ egyenlő
az általad megadott stringgel). Más lenne a helyzet, ha nem
pointerként, hanem stringként difiniáltad volna.

char anyad[]="1234";

Így kellett volna.

Én még sokszer ezt is bele szoktam tenni:

char anyad[]="1234\0";

csak a tuti kedvéért, nagyon kritikus helyeken, bár még nem
tapasztaltam, hogy a változóként megadott string után ne
fordult volna be a '\0'.

Én ezt így írtam volna meg:

unsigned char anyad[]="1234\0";

i=0;while(anyad[i])i++;
printf("%5d",i);printf("\n");

> Sol omnibus lucet.

A plusz \0 teljesen fölösleges, ennyi erővel akár még azt is mögéírhatnád, hogy anyad[strlen(anyad)]='\0'; :).
"...bár még nem tapasztaltam, hogy a ... string után ne fordult volna be a '\0'":
Ez nem mágia meg implementációfüggő, hogy most vagy befordul, vagy nem, hanem a nyelv része, azaz mindenhol befordul. A literális '2'-t sem kell '(1+1)'-nek írni, mondván "bár még nem láttam, de hátha nem fordul be a 2"...

Ez világos, és írtam is: nem tapasztaltam még. Viszont sokszor
dolgozom kísérleti jellegű rendszerekkel (főleg a beágyazott
kategóriában), amelyeknél előfordulnak olyan fordító_bugok,
amelyeket egy kis mágiával orvosolni lehet. Ilyen tapasztalatok
birtokában az ember óvatosabban jár akkor is, amikor papíron
nincs semmi veszély.

Szerintem ez a nézőpont szakmailag akceptálható.

Sokszor választok olyan megoldást, amiről tudom, hogy fölösleges,
de például segít a kód későbbi megértésében. És még sorolhatnám
mivel rongálom a C kódot. Számomra egyetlen mérce van: a
használhatóság - a legtágabb értelemben véve.

> Sol omnibus lucet.

Azok szoktak ezt megszivni, akik nem tudjak, mi a kulonbseg 'a' es "a" kozott.

További Off:
A legviccesebbek azok a rendszerek, ahol a pointer négybájtos, az int kétbájtos, a NULL pedig tévesen "0"-ként van #define-olva (ugyebár "0L" lenne a korrekt).
Ilyenkor egy printf ("%p %d", NULL, 12);
bármit is kiírhat, pl azt, hogy 0000000c 23

Szerintem nem.

"According to the language definition, a constant 0 in a pointer context is converted into a null pointer at compile time. "

Más kérdés, hogy a printf hívásakor nem tudja eldönteni, hogy milyen típusú a paraméter, ezért ott célszerű cast-olni a NULL-t, hogy valóban pointer legyen.

Már csak ezért is: "In C, each pointer type has its own null value, and sometimes they have different representations."

KisKresz

Kivéve C++-ban, ahol ez a bug nem bug, hanem feature. Ezt persze nem ismerhették be, ezért inkább előálltak a nullptr című termékkel, a kompatibilitás nagyobb dicsőségére.