Geheugen-adressen printen
27 januari 2011 - 16:05   
geplaatst door: Syncan
Hallo,

Ik zit als beginner een beetje te klooien met pointers en nu wilde ik voor de aardigheid bekijken welke geheugen-adressen het systeem gebruikt voor de variabelen.

Het stukje code dat ik daarvoor gemaakt had ziet er zo uit:


Int a;
a = 25
printf(" A= %d\n" , &a );

Ik krijg dan op de printf de volgende foutmelding:
Format '%d' expects type 'int', but argument 2 has type 'int *'

Hij retourneert trouwens wel een waarde: -1073744324, of als ik placeholder voor hex-getallen gebruik, BFFFF63C


Ik snap wel wat de fout is, maar hoe moet het dan wèl?
Zelfde vraag voor het uitprinten van pointers...

Bij voorbaat dank!

Geheugen-adressen printen
27 januari 2011 - 16:20    reactie #1
geplaatst door: Pieterr
Je kunt het adres naar een int "casten":

printf(" A= %d\n" , (int) &a );
"One experiment is worth a thousand expert opinions."
Geheugen-adressen printen
27 januari 2011 - 16:32    reactie #2
geplaatst door: Syncan
Aha, die had ik nog niet geleerd  :worship:
Maar wel gek eigenlijk, want als je bij placeholder al %d geeft, dan moet-ie het toch snappen dat het een int is?
Maar goed,  hoe kan je de inhoud van een pointer printen? Dat is geen int, vandaar de vraag...
Geheugen-adressen printen
27 januari 2011 - 17:23    reactie #3
geplaatst door: Pieterr
Op dezelfde manier:


int main()
{
   int a = 5;
   int *pa = &a;
   
   printf("a = %d\n", a);
   printf("pa = %.8x\n", (int) pa);
   printf("*pa = %d\n", *pa);
   
   return 0;
}
"One experiment is worth a thousand expert opinions."
Geheugen-adressen printen
27 januari 2011 - 17:26    reactie #4
geplaatst door: Syncan
Da's duidelijk. Bedankt!  :reading:
Geheugen-adressen printen
27 januari 2011 - 18:31    reactie #5
geplaatst door: Pieterr

Citaat
Syncan om 16:32, 27-01-2011
Maar wel gek eigenlijk, want als je bij placeholder al %d geeft, dan moet-ie het toch snappen dat het een int is?

De compiler probeert je te waarschuwen voor het feit dat er een "int" verwacht wordt als argument in de printf aanroep. Merk op dat dit al een vrij geavanceerde feature van de compiler is. De compiler heeft ingebouwde kennis van de specifieke karakters ("%d") die in de printf string gebruikt worden.

Door er een "cast" voor te plaatsen vertel je aan de compiler dat je weet wat je aan het doen bent. En hopelijk is dat ook zo.  :smile:  In het algemeen is het gebruik van "casts" af te raden maar soms heb je ze inderdaad nodig om van bepaalde compilerwaarschuwingen af te komen.

"One experiment is worth a thousand expert opinions."
Geheugen-adressen printen
27 januari 2011 - 18:42    reactie #6
geplaatst door: Macceraar
Pointers naar int casten is niet zo'n goed idee. int kan iets heel anders zijn volgens de spec, en inderdaad past een pointer van LP64 (het model voor 64-bit) niet. Als je per sé naar int moet, gebruik dan intptr_t o.i.d., en voor printf heb je %p (die je technisch void * moet geven, maar het is ietwat moeilijker om daarmee in de problemen te komen op de meeste systemen).
Geheugen-adressen printen
27 januari 2011 - 19:14    reactie #7
geplaatst door: Syncan
Ja, ik moet het allemaal nog leren, Macceraar. Je zegt een hoop zaken die mij onbekend voorkomen. Ik heb een Macbook Air ( net nieuw ) en daarvan weet ik niet of het 32- of 64-bits is. Verder weet ik niet wat LP64 is en ook niet wat intptr_t is, al denk ik dat dat laatste een conversie-functie is.
Ook %p die technisch void is, ben ik nog niet tegengekomen in mijn leerboek  :cheesy:

Waar kan ik trouwens een volledige lijst vinden van de Printf-placeholders? Ik ken er maar een stuk of vijf, zes en het lijkt me dat er vast meer zijn...

Geheugen-adressen printen
27 januari 2011 - 19:52    reactie #8
geplaatst door: Pieterr
"One experiment is worth a thousand expert opinions."
Geheugen-adressen printen
27 januari 2011 - 19:57    reactie #9
geplaatst door: Macceraar
Sorry dat het meteen zo moeilijk is, maar ik moest even een paar correcties het draadje in gooien.

LP64 staat voor long-pointer-64, dus dat long ints en pointers 64 bits zijn. En int impliciet 32, dus minder dan de pointer. Verschillende systemen kunnen verschillende groottes hebben, en het is beter om daar rekening mee te houden als je wilt dat je code zonder al te veel aanpassingen op andere systemen draait. De stap van PPC naar x86 en naar 64-bit was lang niet zo groot geweest als meer software niet zo sterk op de 'huidige' systemen was gericht.

Iets concreter: als je voor 64-bit compileert (standaard tegenwoordig), en je pointer omzet naar een int, dan zal dat werken op je Air, maar er gaat informatie verloren. Er zijn meerdere pointers die dezelfde int geven, en als je de int weer omzet naar een pointer zul je zien dat hij niet meer werkt.

intptr_t is een type gedefinieerd in <stdint.h>. Dat is een integer die een pointer kan bevatten. Als je zeker weet dat je het nodig hebt, is het het beste om dat type te gebruiken. Maar meestal is het beter om in de eerste plaats niet met zulke praktijken bezig te zijn.

%p neemt een void * net zoals %d een int en %g een double nemen. printf("%p\n", (void *)some_pointer) dus, om het helemaal netjes te doen.

Er zijn op het internet en op je computer specificaties en documentatie te vinden. Alleen al een paar manieren om man pages te bekijken:
- Terminal: man 3 printf
- Xcode: Help -> Open man Page... -> 3 printf
- Xcode: Help -> Developer Documentation -> printf

De 3 is bij de bovenste twee omdat er ook een "1 printf" is, een shellcommando, dat anders voorrang krijgt. Voor veel functies is de 3 (of 2, die je bij system calls ziet) niet nodig en kan je alleen de naam geven.

Hopelijk is dit een klein beetje beter te begrijpen, al heb ik niet de tijd om op alles helemaal in te gaan.

Geheugen-adressen printen
27 januari 2011 - 19:58    reactie #10
geplaatst door: Syncan
Dank je wel! Dat zijn er een hoop!  :wacko:
Geheugen-adressen printen
27 januari 2011 - 20:23    reactie #11
geplaatst door: Syncan

Citaat
Macceraar om 19:57, 27-01-2011
Sorry dat het meteen zo moeilijk is, maar ik moest even een paar correcties het draadje in gooien.

LP64 staat voor long-pointer-64, dus dat long ints en pointers 64 bits zijn. En int impliciet 32, dus minder dan de pointer. Verschillende systemen kunnen verschillende groottes hebben, en het is beter om daar rekening mee te houden als je wilt dat je code zonder al te veel aanpassingen op andere systemen draait. De stap van PPC naar x86 en naar 64-bit was lang niet zo groot geweest als meer software niet zo sterk op de 'huidige' systemen was gericht.

Iets concreter: als je voor 64-bit compileert (standaard tegenwoordig), en je pointer omzet naar een int, dan zal dat werken op je Air, maar er gaat informatie verloren. Er zijn meerdere pointers die dezelfde int geven, en als je de int weer omzet naar een pointer zul je zien dat hij niet meer werkt.

intptr_t is een type gedefinieerd in <stdint.h>. Dat is een integer die een pointer kan bevatten. Als je zeker weet dat je het nodig hebt, is het het beste om dat type te gebruiken. Maar meestal is het beter om in de eerste plaats niet met zulke praktijken bezig te zijn.

%p neemt een void * net zoals %d een int en %g een double nemen. printf("%p\n", (void *)some_pointer) dus, om het helemaal netjes te doen.

Er zijn op het internet en op je computer specificaties en documentatie te vinden. Alleen al een paar manieren om man pages te bekijken:
- Terminal: man 3 printf
- Xcode: Help -> Open man Page... -> 3 printf
- Xcode: Help -> Developer Documentation -> printf

De 3 is bij de bovenste twee omdat er ook een "1 printf" is, een shellcommando, dat anders voorrang krijgt. Voor veel functies is de 3 (of 2, die je bij system calls ziet) niet nodig en kan je alleen de naam geven.

Hopelijk is dit een klein beetje beter te begrijpen, al heb ik niet de tijd om op alles helemaal in te gaan.

Het is al een stuk beter te begrijpen  :wink:
Ik zal die man-pages ook nalezen. Ik kom oorspronkelijk van Windows, waar ik met Visual C# gewerkt heb. C werkt naar mijn idee veel meer met pointers. Ik heb drie boeken aangeschaft die elkaar ( hopelijk ) aanvullen: Learn C on the Mac, Learn Objective C on the Mac en Learn Cocoa on the Mac, allemaal uitgegeven bij Apress.
Samen met wat ik hier op dit forum vind, kan ik dus voorlopig nog wel even vooruit  :smile: