r2d290 Skrevet 30. november 2012 Del Skrevet 30. november 2012 (endret) Jeg har følgende kode som skal skrive inn tall i array a og så kopiere det til array b. Hvorfor skriver den nederste linja ut en minneverdi og ikke innholdet i array b posisjon 0? Utskriften av *p fungerer jo fint. [ #include <stdio.h> #define MAX 10 int main() { int a[MAX]; int b[MAX]; int i; int *p; int *q; printf( "%d\n", MAX); p=a; for(i=0; i<MAX; i++) a[i]=i*2; printf("kakemann %d\n",*p); q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } printf("tallet %d\n",b[7]); printf("%d\n",*q); } Endret 30. november 2012 av r2d290 waits for Obi-Wan Lenke til kommentar
etse Skrevet 30. november 2012 Del Skrevet 30. november 2012 Jeg testet koden, og jeg fikk ut følgende: 10kakemann 0 tallet 14 0 Er ikke det du forvnenter? Linje 1: Du skriver du max, som er 10 Linje 2: Du skriver ut det som er lagret i p[0], som er 0*2 = 0 Linje 3: Du skriver ut tallet i b[7], som er 7*2 = 14 Linje 4: Du skriver ut det som er i q[0] som er 0*2 = 0 Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 (endret) Jeg får: 10 kakemann 0 tallet 14 -1604583496 edit: Men, da tenker jeg vel tydeligvis riktig i allefall Takk takk! Endret 30. november 2012 av r2d290 waits for Obi-Wan Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Linje 4: Du skriver ut det som er i q[0] som er 0*2 = 0 Forandre q[0] til q[2]. Lenke til kommentar
etse Skrevet 30. november 2012 Del Skrevet 30. november 2012 Hvilken komplilator bruker du? For virker som det du skriver ut ikke er minneadressen med rett og slett "garbage". (At du ikke har gitt det noen verdi). Dåg fungerer det helt fint i GCC. Dåg er det litt skummelt det du prøver på her: q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } Her lurer jeg litt på hva du egentlig tenkte? Ville endret det til q=b; for(i=0; i<MAX; i++) { *q[i] = *p[i]; } Lenke til kommentar
etse Skrevet 30. november 2012 Del Skrevet 30. november 2012 (endret) Forandre q[0] til q[2]. Ser nå at det er noe rot med pekerene etter den forloopen jeg nevner i forrige post for(i=0; i<MAX; i++) { *q++ = *p++; } etter dette vil q ha adressen til q[MAX] og ikke q[0]. Noe som vil lage store problemer. Løses med å gjøre denne lille endringen: q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } q=b; Vil legge til en interesant bemerkelse jeg nettop hadde. Jeg endre koden til følgende: #include <stdio.h> #define MAX 10 int main() { int a[MAX]; int b[MAX]; int i; int *p; int *q; p=a; for(i=0; i<MAX; i++) a[i]=i*2; q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } for(i=0; i<MAX; i++) { printf("%d\n",q[i]); } } og får da følgende output: 02 4 6 8 10 12 14 16 18 Som er det man ville forventet, selv om koden er helt feil. Noe som forklarer hvorfor det så riktig ut første gang jeg kjørte koden. Årsaken til dette er at arrayene a og b ligger rett etter hverandre i minnet. Så når man trodde man skrev ut q[0] (som skulle være array b), skrev man egentlig ut q[max+0] som tilsvarer p[0], og dermed array a. Dette ser man tydelig om jeg skriver ut minneadressene. Endret 30. november 2012 av etse Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 (endret) There we go. :> Kult triks: 23 printf("%d\n",q[-8]); For å utdype: koden og logikken din er i utgangspunktet helt riktig. Problemet er at du inkrementerer pekeren som forandrer verdien på den, så du er nødt til å "resette" den for å aksessere fra 0 igjen. Dette kan gjøres på flere måter. Her er to: q = b; q -= MAX; // funker siden det var dette du økte den med Edit: kan legge ved noe mer info som kan være nyttig. Etse: hva kompilerte du med. O3? Uansett, det kan være flere grunner til at du får 0 der. Ene kan være at verdien som tilfeldigvis lå på minneplassen var 0. Mer sannsynlig er det at kompilatoren gjorde en memset( 0 ) på hele minneområdet før kjøring. Endret 30. november 2012 av Lycantrophe Lenke til kommentar
etse Skrevet 30. november 2012 Del Skrevet 30. november 2012 Edit: kan legge ved noe mer info som kan være nyttig. Etse: hva kompilerte du med. O3? Uansett, det kan være flere grunner til at du får 0 der. Ene kan være at verdien som tilfeldigvis lå på minneplassen var 0. Mer sannsynlig er det at kompilatoren gjorde en memset( 0 ) på hele minneområdet før kjøring. Jeg så over koden en gang til. Og som nevnt over glemte jeg å tenke på at GCC har en tendens til å legge elementer på stacken rett etter hverandre. Og jeg skrev egentlig ut det andre arrayet. Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Jeg fikk bare 0 og annen garbage på min maskin, men det er definitivt fordi man herjet utenfor allokert minne. Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 Forandre q[0] til q[2]. Hva mente du med dette? Stemmer det ikke at det er q0 jeg printer fra? Hvilken komplilator bruker du? For virker som det du skriver ut ikke er minneadressen med rett og slett "garbage". (At du ikke har gitt det noen verdi). Dåg fungerer det helt fint i GCC. Dåg er det litt skummelt det du prøver på her: q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } Her lurer jeg litt på hva du egentlig tenkte? Ville endret det til q=b; for(i=0; i<MAX; i++) { *q[i] = *p[i]; } Litt usikker på kompilator. Trodde det var GCC. Jeg bruker Code::blocs og det som følger med til den av kompilator. På linux. Det andre eksempelet ditt ga kompileringsfeil: Invalid type argument of unary * (have int). Jeg synes det ser ut til at du øker arrayet q og arrayet p, men disse er jo pekere, ikke arrays? Ser nå at det er noe rot med pekerene etter den forloopen jeg nevner i forrige post for(i=0; i<MAX; i++) { *q++ = *p++; } etter dette vil q ha adressen til q[MAX] og ikke q[0]. Noe som vil lage store problemer. Løses med å gjøre denne lille endringen: q=b; for(i=0; i<MAX; i++) { *q++ = *p++; } q=b; Stemmer stemmer. Eller q=&b[0]; som blir det samme, sant? Jeg forstår nå hvorfor dette gikk galt. Men hvorfor fungerte det da for deg? Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Hva mente du med dette? Stemmer det ikke at det er q0 jeg printer fra? Nei. q++ øker verdien til pekeren (altså hvor den peker). Når løkken din er ferdig peker q på b[10], ikke b[0]. Litt usikker på kompilator. Trodde det var GCC. Jeg bruker Code::blocs og det som følger med til den av kompilator. På linux. Det er nok gcc. Det andre eksempelet ditt ga kompileringsfeil: Invalid type argument of unary * (have int). Jeg synes det ser ut til at du øker arrayet q og arrayet p, men disse er jo pekere, ikke arrays? Det stemmer. q[5] "returnerer" en int, ikke en peker til. Det er det samme som å gjøre *(q+5). Det du har gjort er riktig, det er ikke i løkken feilen din er. Stemmer stemmer. Eller q=&b[0]; som blir det samme, sant? Jeg forstår nå hvorfor dette gikk galt. Men hvorfor fungerte det da for deg? Ja, det vil bli det samme. Det fungerte nok for han fordi kompilatoren hans plasserte arrayene etterhverandre. Hadde det ikke blitt gjort hadde han også fått garbage. Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 [...] Som er det man ville forventet, selv om koden er helt feil. Noe som forklarer hvorfor det så riktig ut første gang jeg kjørte koden. [...] Mens jeg som tydeligvis har et annet oppsett, får en helt annen out-print: 153392856 32767 153392904 32767 0 5 0 0 1625339757 32537 Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 (endret) Det kommer gjerne av versjon, flagg m.m. Du får åpenbart garbage. Prøv å sette -O3 som kompileringsflagg. Endret 30. november 2012 av Lycantrophe Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 Hvordan setter man kompileringsflagg med code::blocs / gcc i linux? Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Jeg aner ikke hvordan det gjøres i Code::Blocks, aldri rørt det. Kompilerer fra kommandolinje, da slenger jeg bare på -O3. Det er sikkert en "compiling options" eller "project options" eller noe. Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 Skal ta en titt. Tusen takk for hjelpen! Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Bare å ringe om det er noe. Lenke til kommentar
r2d290 Skrevet 30. november 2012 Forfatter Del Skrevet 30. november 2012 Will do! Lenke til kommentar
etse Skrevet 30. november 2012 Del Skrevet 30. november 2012 Stemmer stemmer. Eller q=&b[0]; som blir det samme, sant? Jeg forstår nå hvorfor dette gikk galt. Men hvorfor fungerte det da for deg? Problemer er at med det siste eksempelet så endrer du verdien til pekeren Q, Så når du skal skrive ut verdiene så har denne en helt annen verdi. Med andre ord, etter forloopen så vil q[0] ikke lenger være array b, men i stede array a. Kan prøve å forklare hvorfor det fungerte for meg. Lager først en tegning over minnet. Se for deg at minner ser noe slik ut før du begynner. I begynnelsen setter programmet av minne til arrayene A og B. For å ikke gjøre ting for vanskelige, har jeg valgt å bruke charater array (hvor hvert element tar 1 byte), og satt MAX til 8 Etter å ha satt av minnet, lar jeg også pekerene q og p peke på hvert sitt array Legg merke til at arrayene her ligger rett ved siden av hverandre, og at q[0] vil være verdien som ligger lagret på minneadresse 0x00012, mens p[0] vil være det som ligger på 0x00020. La oss så gå gjennom den første for-loopen og fylle opp array A med verdier, minner vil da se ut som følger: Alt ser fortsatt helt fint ut. Og verdiene er bare lagt til array A slik vi ønsker. La oss nå gå gjennom den andre for-loopen. Her ser arrayene helt fine ut, men som du ser har verdiene som ligger lagret i Q og P endret seg. Q har nå adressen til første element i A, i stede for første element i B, mens P peker på noe minne som ikke er allokert Dette betyr at når jeg nå prøver å skrive ut det som ligger på adressen lagret i Q, skriver jeg altså ut array A, i stede for Array B slik jeg ønsket. Og man får derfor kode som ser ut som det fungerer, men ikke fungerer helt som det skal. Men da er spørsmålet, hvorfor fungerer det hos meg og ikke dere? Vel, svaret er at ting trolig ligger allokert i minner litt annerledes hos dere. C garanterer ingenting om hvordan den legger ting i minnet. Og dette gjør at når man begynner å gjøre slike feil. Så vil man kunne få helt uventet oppførsel. Lenke til kommentar
Lycantrophe Skrevet 30. november 2012 Del Skrevet 30. november 2012 Men da er spørsmålet, hvorfor fungerer det hos meg og ikke dere? Vel, svaret er at ting trolig ligger allokert i minner litt annerledes hos dere. C garanterer ingenting om hvordan den legger ting i minnet. Og dette gjør at når man begynner å gjøre slike feil. Så vil man kunne få helt uventet oppførsel. Windows, Linux eller OS X? Hvilken gcc-versjon? Hvilke kompilatorflagg? Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå