PDA

View Full Version : How to get Pointer Values?




Jordan72
Nov 23, 2005, 04:13 PM
First, I want -method: to recieve an id pointer. Second, I want to obtain the value of the id pointer in a form that I can store it in a file and then retrieve it.

How do I get an id pointer value?

-method:(id)myPointer // first step
{
...//what do I do here?
}



caveman_uk
Nov 24, 2005, 02:53 AM
Why do you want the value of the pointer only to save it in a file? I may be wrong but I would have thought it was a pointless thing to save between sessions as the section of memory it points to will be meaningless the next time the program runs.

Surely the value the pointer points to would be a better thing to store between sessions.

robbieduncan
Nov 24, 2005, 04:54 AM
caveman_uk is exactlly correct. The pointer points to an address in memory. Next time your program runs this memory is unlikely to belong to your program.

If you mean this:

"I want to save the state of the object pointed at to disk and restore it later"

then we can make some progress. As you do not appear to know the type of the object you are pointing at (id is void* pointer) we cannot rely on any object specific behaviour.

The standard Cocoa way of doing this is via NSCoding. You need NSCoding compliant objects for this to work. Many objects are NSCoding compliant.


...
NSString *path = ....

- (void) saveToDisk:(id) object
{
[NSKeyedArchiver archiveRootObject:object toFile:path];
}

- (id) readFromDisk
{
return [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}


Obviously this will always save to the same path. You might want to pass the path into the methods. Also if you are going to serialise a lot of objects to disk don't put one per file, put them all in an NSDictionary or NSArray and save that.

Jordan72
Nov 24, 2005, 05:30 PM
Maybe a NSMutableArray would be better place. I agree a file isn't the best place.

Why I want to get the value of the pointer: I'm trying, just for fun, to create my own Autorelease Class. If I send the pointers to -method: and save them, I can locate what embedded pool the object should be added to and what pool should deallocate it.

Anyhow, that's the why. I'm still wondering how to get those pointer values. Anyone know that?

robbieduncan
Nov 24, 2005, 05:39 PM
You are not making sense. The value of a pointer is whatever is contained at the address of the memory the pointer is pointing at! A pointer is simply a memory address. id is simply void *. It's a pointer to an Obj-C Object. Of what type you don't know! You can use standard Obj-C to find out what type the object is. Based on that you can find out it's 'value'.

Jordan72
Nov 24, 2005, 06:13 PM
You are not making sense. The value of a pointer is whatever is contained at the address of the memory the pointer is pointing at!

Actually I mean the value of the pointer variable, not the value of what the pointer is pointing to. So it's an address. How do I get that address and what kind of variable would be appropriate to hold an address?

robbieduncan
Nov 25, 2005, 02:37 AM
Actually I mean the value of the pointer variable, not the value of what the pointer is pointing to. So it's an address. How do I get that address and what kind of variable would be appropriate to hold an address?

An address is a 32 or 64 bit int depending on what sort of platform. On OSX unless your code has jumped through a lot of hoops even on a G5 and int is 32 bit.

To get the address you just reference the pointer variable:

MyObjCObject *pointer = [[MyObjCObject alloc] init];

int address = pointer;


Note the compiler might complain about you assigning a pointer to an int.

This is very basic C!

caveman_uk
Nov 25, 2005, 03:33 AM
Maybe a NSMutableArray would be better place. I agree a file isn't the best place.

Why I want to get the value of the pointer: I'm trying, just for fun, to create my own Autorelease Class. If I send the pointers to -method: and save them, I can locate what embedded pool the object should be added to and what pool should deallocate it.

Anyhow, that's the why. I'm still wondering how to get those pointer values. Anyone know that?
You could end up having a lot of fun with memory leaks if you do this wrong. The thing about autorelease is that I've always been told that it's better to use release unless you have a good reason to use autorelease (like when you want to return an autoreleased value). It makes your memory footprint smaller. It's not that hard to end up with an autorelease pool of hundreds or thousands of objects. Unless you're code is really good you'll end up with code that's like running in molasses. Edit: I'm talking here about rolling your own autorelease pool

You may find the articles at this link (http://www.mulle-kybernetik.com/artikel/Optimization/) useful.

Jordan72
Nov 25, 2005, 03:42 PM
caveman_uk:

Actually, this autorelease class I'm attempting to create, "just for fun" is in straight Objective-C, not using the Foundation, so my comment early about an NSArray was an error, because that would be unavailable and defeat the purpose of my pointer question. Sorry about that.

robbieduncan:

I checked the size of id and int for my platform with the sizeof(id) and sizeof(int). Both return four bytes.

I tried your address pointer concept above. Yes, I did get a couple of warnings about these assignments. But, it all worked out below!

id idpointer1;
id idpointer2;
id idpointer3;

int *intpointer;

idpointer1 = [[ClassOne alloc] init];

intpointer = idpointer1;

idpointer3 = intpointer;

[idpointer3 testMethod]; //The test method was called!


Thanks for the helps guys. Cool, I'm pretty stoked to know this! Off hand, is there anyway to remove these warnings by writing the code some other way? I've read that it is better not to write code with warnings.

Yes, these may be basic questions, but everyone has to ask them atleast once in their programming career.

robbieduncan
Nov 25, 2005, 04:13 PM
Don't declare it as a pointer to an int! I was suggesting using int not int*. You can use void * pointers to store pointers to objects (where you are using intpointer). Or just use id which is void * anyway!

Jordan72
Nov 25, 2005, 04:58 PM
Okay, now these this version compiles without warnings. Thanks for the help. I've never used void and really don't know what it is.


id idpointer1;
id idpointer2;

void *voidpointer;

idpointer1 = [[ClassOne alloc] init];

voidpointer = idpointer1;

idpointer2 = voidpointer;

[idpointer2 testMethod];

robbieduncan
Nov 25, 2005, 05:08 PM
void * is basically a pointer to anything. int * is a pointer to an int, char * is a pointer to char and so on. It's worth noting that all pointers are basically the same. The point in the different pointer types is that it enables the compiler to check stuff better and makes pointer arithmetic work. For example:


int x = 5;
int *intpointer = &x;
intpointer++; // This is not safe here but the pointer has just been moved 4 bytes in RAM on most systems.

char a ='a';
char *charpointer = &a;
charpointer++; //Again not safe here but the pointer has only been moved 1 byte.


Make sense?

Jordan72
Nov 25, 2005, 05:28 PM
That makes sense.

A pointer has two parts to it: it is an address and a type. I can see how to get it's address.

Out of curiosity, do you know how the type is stored with a pointer's address? Not that I have a reason to get it, but now that we're talking about it, is it possible to query a pointer for it's type?

robbieduncan
Nov 25, 2005, 05:44 PM
In general c terms, no. The compiler will warn you if you try assign the address of one type to a pointer of another.

In Obj-C terms you can ask an object what type it is.


id anObject = [NSNumber numberWithInt:0];

if ([anObject isMemberOfClass:[NSNumber class]])
{
NSLog(@"Is a NSNumber");
}

if ([anObject isMemberOfClass:[NSArray class]])
{
NSLog(@"Is a NSArray");
}


Should print "Is a NSNumber" but not "Is a NSArray".

If you just want to find the name of the class that anObject is you can use this (not it's a c-string, i.e. a null terminated array of characters)


const char *name = [anObject class]->name;


If you want the name as a NSString this should work:


NSString *className = [NSString initWithCString:[anObject class]->name];


Note I've not tested any of this: I've just typed it into the reply box.

Edit to add: You need #import <objc/objc-runtime.h> for the ->name stuff to work.

savar
Nov 25, 2005, 05:45 PM
That makes sense.

A pointer has two parts to it: it is an address and a type. I can see how to get it's address.

Out of curiosity, do you know how the type is stored with a pointer's address? Not that I have a reason to get it, but now that we're talking about it, is it possible to query a pointer for it's type?

The type isn't actually available at run-time. The type is only used by the compiler to make sure you don't blatantly misuse anything. (E.g. accidentally refer to a character through an int pointer...this is an easy typo or brainfart but if you've declared types for the pointers then the compiler knows you messed up.) After type-checking everything, your program is compiled and all of the type information is lost. (In straight C. Other languages, such as Obj-C and Java store type information inside objects, but in general you can't ever infer type from a primitive such as int or int *.)

Jordan72
Nov 25, 2005, 07:08 PM
The type isn't actually available at run-time. The type is only used by the compiler to make sure you don't blatantly misuse anything.

Doesn't pointer arithmetic happen during runtime? How would it know to increment or decrement for different types? What am I missing here?

savar
Nov 25, 2005, 08:08 PM
Doesn't pointer arithmetic happen during runtime? How would it know to increment or decrement for different types? What am I missing here?

Yeah, pointer arithmetic is done at runtime, but the compiler modifies the addend based on the type. So if you want pointer++, and the compiler knows that pointer is int *, it will add 4 to pointer, if pointer is short it will add 2, etc. If you wanted to add, say, 10 to the pointer, then the compiler would know to insert code to multiply that number by 4 (add 40) if it was an int *, 2 (add 20) if it was a short etc. This is my understanding, feel free to correct me if somebody knows better.

HiRez
Nov 26, 2005, 03:00 PM
You can, however, determine the size of an object a pointer points to at runtime using the sizeof() function:#include <stdio.h>

typedef struct {
int x;
int y;
int z;
int w;
} Matrix;

int main (int argc, const char * argv[]) {
int *intPtr;
char *charPtr;
Matrix *mPtr;

printf("int size = %d\n", sizeof(*intPtr));
printf("char size = %d\n", sizeof(*charPtr));
printf("matrix size = %d\n", sizeof(*mPtr));

return 0;
}returns:int size = 4
char size = 1
matrix size = 16...which might be enough information to guess at the type if you have a limited number of possible types you're working with.

robbieduncan
Nov 27, 2005, 04:07 AM
HiRez: That's very nice but I don't think it will work for ObjC objects as they will all have the same size as each object is an instance of the same struct (objc_class).

The class name, the instance variables etc are all pointers to memory outside the struct so all the structs will have the same size.

techgeek
Nov 28, 2005, 09:35 AM
You can, however, determine the size of an object a pointer points to at runtime using the sizeof() function:#include <stdio.h>

typedef struct {
int x;
int y;
int z;
int w;
} Matrix;

int main (int argc, const char * argv[]) {
int *intPtr;
char *charPtr;
Matrix *mPtr;

printf("int size = %d\n", sizeof(*intPtr));
printf("char size = %d\n", sizeof(*charPtr));
printf("matrix size = %d\n", sizeof(*mPtr));

return 0;
}returns:int size = 4
char size = 1
matrix size = 16...which might be enough information to guess at the type if you have a limited number of possible types you're working with.

Actually in this case the sizeof() is worked out at compile time (in fact at pre processing) and effectively becomes hard coded for the runtime.
printf("int size = %d\n", sizeof(*intPtr));
printf("char size = %d\n", sizeof(*charPtr));
printf("matrix size = %d\n", sizeof(*mPtr));
Becomes:
printf("int size = %d\n", 4);
printf("char size = %d\n", 1);
printf("matrix size = %d\n", 16);