Verwijderd schreef op vrijdag 02 mei 2008 @ 11:02:
[...]
1) Cast een Object* naar een integer. Voer hier de rekenkundige operatie op uit. Cast de integer terug naar een Object*. Wijst de pointer nu naar het zelfde Object als wanneer je de rekenkundige operatie direct op de Object* had uitgevoerd?
2) Cast een Object* naar een integer. Geef deze integer door aan een stuk assembly code dat in dezelfde process draait. Als deze assembly code de integer direct als geheugen adres gebruikt, krijgt het dan gegarandeerd de eerste byte van het Object terug waar Object* naar wees?
Zoals gezegd, ik weet het niet meer zeker, maar volgens mij geeft C++ je niet deze garantie.
Misschien begrijp ik je verkeerd.... maar als je een pointer cast naar een ander type blijft het gewoon een 32 (of 64) bits adresverwijzing. Neem de volgende pointer:
Daarmee zeg je in feite: pointervar is een adres waar een integer staat opgeslagen. Als ik dat cast naar een SpecialObject (Wat dus resulteert in SpecialObject *pointervar), dan zal het nog steeds hetzelfde geheugenadres zijn, maar zal de compiler het zo intreperteren dat er op dat adres een SpecialObject staat. De waarde van de pointer zou niet mogen veranderen als je het simpelweg cast naar een ander type, omdat de inhoudelijke data nog steeds op dezelfde plek staat.
Ook leuk: in C++ kan je er ook voor kiezen om geen type aan je pointer te geven. Dan maak je gebruik van een void pointer (void *pointervar). In dit geval zal je wel gebruik moeten maken van casting, om de data alsnog te kunnen interpreteren. Zou ik dan niet gegarandeerd de eerste byte terug krijgen van de originele void pointer, zou ik een probleem hebben.
Als ik de pointer int *pointervar gebruik, kan ik ook vervolgens zeggen:
code:
1
2
3
| int *pointervar = (int*)malloc(sizeof(int) * 20); //een pointer naar een ruimte ter grote van 20 ints.
int *var = &pointervar[2]; |
Deze code zal misschien niet helemaal prettig werken, omdat het geheugen nog niet geinitialiseerd is, maar het gaat om het idee. Hier reserveer ik geheugen ter grote van 20 ints en kan door gebruik te maken van square brackets, het adres achterhalen dat zich 2 integers verderop begint (in het geval van 2 x 32 bit integers, dus het adres van 64 bits verderop in het geheugen). Let ook op, dat ik het cast naar een int pointer, omdat malloc een void pointer retouneerd.
Ik kan bijvoorbeeld ook dit doen:
code:
1
2
3
| unsigned char *pointervar = (unsigned char*)malloc(sizeof(unsigned char) * 20); //een pointer naar een ruimte ter grote van 20 unsigned chars.
unsigned char *var = &pointervar[2]; |
Hier zal je stappen van 8 bits maken. Dus in dit geval zal ik het adres van 2 * 8 bits verderop terug krijgen.
Dit hangt ook enorm af van de memory management strategie achter malloc. Maar je kan (volgens mij) er wel van uit gaan dat malloc over het algemeen continue blokken reserveert.
Ik heb een tijdje terug voor de hobby een mini os'je gemaakt. Ik heb daar testimplementaties van gemaakt met behulp van zowel de GNU als de MS compiler. En bij beide kon ik uitgaan van het gedrag wat ik zojuist beschreven heb. (Wat het schrijven van een malloc functie wel gemakkelijker maakte). Als de compiler namelijk zelf de doorverwijzing intern zou beheren, zou ik nooit een goede memory manager kunnen schrijven (in de vorm van malloc of whatever).
Om even een vergelijking met C# te maken. Normaal gezien kan ik daar dit geintje niet uithalen. (Wellicht in een unsafe context? Iemand?). Omdat daar gebruik wordt gemaakt van references, kan je het wel naar een ander object laten wijzen, maar kan je niet direct aan de pointer zelf gaan sleutelen.
edit:
Ik heb ook nog een tutorial gevonden voor je die dit allemaal uitlegd:
http://www.cplusplus.com/doc/tutorial/pointers.html Hierin wordt ook ingegaan op andere onderwerpen zoals pointer arithmatics etc.
edit 2:
Hier een testappje van de voorgaande concepten. Let ook op de testpointer in de loop... het adres wordt hier direct toegewezen aan de pointer. Je ziet ook dat alle element adressen precies 4 bytes van elkaar verwijderd zijn (een 32bits integer dus).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #include "stdio.h"
#include "stdlib.h"
int main(int argc, char *argv[])
{
int *pointervar = (int*)malloc(sizeof(int) * 20);
printf("Start van geheugenblok: %p\n\n", pointervar);
for (int i = 0; i < 20; i++)
{
pointervar[i] = i;
int * testpointer = &pointervar[i];
printf("waarde bij adres %p: %d\n", &pointervar[i], pointervar[i]);
printf("testpointer waarde: %p\n\n", testpointer);
}
getchar();
return 0;
} |
[
Voor 39% gewijzigd door
Laurens-R op 02-05-2008 14:39
]