views:

619

answers:

6

After I thought that I've understood how they work, I tried this:

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, one
NSLog(@"str2: %x, %@", &str2, str2); //bfffd3c8, two

str1 = str2;
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, two

The value of an pointer (like str1, str2) is a memory address. When you go to that address, you reach the "area" in memory where the object is stored.

But: When I assign str2 to str1, str1 should have as an value the memory address of the same object that's referenced by str2, right? The strange thing here is, that the value of the pointer remains the same (bfffd3cc memory address), where the thing behind that address changes. that's actually completely unlogical to me ;) because I think that the memory address IS the object (or the home of the object in the memory brick, what ever). So I expected this:

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, one
NSLog(@"str2: %x, %@", &str2, str2); //bfffd3c8, two

str1 = str2;
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3c8, two

Otherwise, I still didn't get the point. The relation between the value of the "pointer variable" and the "real value", lets say the object that's sitting behind that memory address.

+10  A: 

Remember that a pointer variable is a variable itself, so it has an address. So &str1 results in the address of the pointer variable, and str1 is an expression that results in whatever the pointer variable is holding - the address of the object it's pointing to.

Assume that:

  • the object holding the NSString "one" is at address 0x00000100
  • the object holding the NSString "two" is at address 0x00000200

Then your pointers might look something like this:

At initialization:

str1
0xbfffd3c8  +---------------+
            |               |
            |  0x00000100   |
            |    ("one")    |
            +---------------+

str2
0xbfffd3cc  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+

=======================================

After the str1 = str2; assignment:

str1
0xbfffd3c8  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+

str2
0xbfffd3cc  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+
Michael Burr
Thanks
Michael Burr
The value of a pointer is the address of the thing pointed to (or NULL, which is represented as zero). A pointer is just a variable which holds a memory address. A memory address is just a number.
tpdi
Perfect answer. Show code that prints the pointer value: NSLog(@"str1: %x, %x, %@",
Martin York
+2  A: 

you are printing the reference of your pointer, which is the address of the pointer, not the value of the pointer.

yx
Thanks! how would I print the address of the thing that the pointer points to?
Thanks
yx
Thanks! That works fine!
Thanks
+1  A: 

str1 is a pointer to a NSString value.

&str1 means: the address of the str1 variable. This is a double indirection.

I guess that you want the address of the value, i.e., str1 itself, not &str1.

Let's assume that the NSString object value containing @"one" is located at address 0x12345678 and @"two" is at 0x1234ABC0.

Initially the value of str1 is 0x12345678 and the value of str2 is 0x1234ABC0. These two values are stored in memory respectively at addresses 0xbfffd3cc and 0xbfffd3c8. These are the addresses of str1 and str2 variables, i.e., values of &str1 and &str2.

When you write str1 = str2, the assignment changes value of str1 to be the same as value of str2, i.e., value of str1 is then 0x1234ABC0. This is the address of the @"two" object. But address of str1 variable (0xbfffd3cc) is not changed.

mouviciel
Thanks. But that's pretty confusing... if str1 is a pointer to the value of an NSString, how can I act on that as if it was an NSString object, i.e. sending messages / invocing methods on it?
Thanks
Because in objective-C objects are always pointers. str1 pointer is a NSString object.
mouviciel
Actually, messages are sent through pointers. So when you do [obj doSomething] you are sending the message "doSomething" to the object pointed to by the pointer "obj".
Vincent Robert
Thanks! The thing that confused me was that the NSLog prints out the value of the NSString object. But %@ is especially for NSString Object values as I know now. I thought that's generally for any object value (although I never understood how this was going to work on any object ;) ). Just for the case someone reads this and is the same way confused.
Thanks
%@ works not only with NSString object but with all objects (not sure if it is only with subclasses of NSObject). It will get a NSString value by sending the -description method to the object.
mouviciel
+1  A: 

Pointers are, in fact, integers with a dedicated arithmetic (IIRC, it is guaranteed that sizeof(int) == sizeof(void*))

If you reference pointers, you'll get the address where it is stored; if the variable is automatic, then you'll get the address in the stack where the pointer is stored: that's why you get those results.

Assignment behave like assignment between integers; in fact:

#include <stdio.h>

int main() {
        char *str1 = "Ciao";
        char *str2 = "Mondo";
        printf("%x\n", str1);
        printf("%x\n", str2);
        str1 = str2;
        printf("%x\n", str1);
}

prints:

:~$ ./a.out
80484f8
80484fd
80484fd
akappa
Thanks! What do you mean by "if the variable is automatic"? Never heard of automatic variables....
Thanks
An automatic variable is a variable declared in a block body.It is called "automatic" because its storage is reclamed automatically at the end of the declaring block.
akappa
+2  A: 

&str1 takes the address of the pointer.

Ok, remember how we said that all things "live" at some address in memory? And that a pointer is just the number, a number that is the address?

Well pointers are things too, and as such they have addresses.

When you print out &str1, you're printing out the memory occupied by the pointer. When you print out str1, you're printing out the value of the pointer, which is the memory address it points to.

When you print out *str1 you're dereferencing the pointer, and printing that prints the value pointed to.


Incidentally, good work: I've read your last two questions, and you're getting it, and to your credit writing code to prove or disprove that your understanding is correct. This is exactly what you should be doing, and you're on the right track.

Part of the problem you're having is that strings are funny things, in that a string really an array of (const) characters, and functions like NSLog are written to do the usual thing with a pointer to char, which is to print the string. Given a pointer to string, it's really looping: dereferencing the pointer, printing the pointed-to character, adding one to the pointer, printing the next character, until the character pointed to is a special character with the value 0, at which point it has found the end of the string and stops printing out characters.

You might find all this easier to understand if you use something like ints and pointers to ints.

tpdi
Thanks
Thanks
Nope... after I've replaced all ) because 2 different objects, and I do get still "one", "two", "two" printed out.
Thanks
No! *str1 dereferences the pointer. So you get the value pointed-to. Now that gets a bit hairy, because I don't know if an NSString is a C-style string (an array of char) or a C++ style string (an object that has an array of char). If it's a C-style string, dereferencing it gives you the first char in the array pointed-to; if it's a C++ style string, it gives you an NSString object.
tpdi
Yeah. Again, try this with ints, it'll be a little easier. After you're comfortable with that, then use strings.
tpdi
Regarding your last edit: Thanks. Well I wanted to understand that on objects, not on "primitive datatypes" like int. But I'll make a little class and then alloc+init it to check it out.
Thanks
NSString is a class with a lot of methods, and I used and convenience allocator there to instantiate and initialize it.
Thanks
+1  A: 

Objects in Objective-C are worked on using pointers. So in order to handle your NSString object, you have to take a pointer to it. Which is what str1 is, a pointer to an NSString object.

If you want to send a message to your NSString, you can use the syntax [str1 doSomething].

If you want to print your string, you have to pass the pointer to NSLog AND tell NSLog that the pointer points to an NSString, which is done by the formatting rule "%@".

Now, if you just want to print the address pointed to by str1, you still have to pass the pointer str1 BUT you must tell NSLog that you are printing it as an hexadecimal value using the formatting rule "%x".

Something like that should print what you want:

// First print str1 as an hexadecimal value
// Then print the content of the NSString object str1 points to
NSLog(@"str1: %x, %@", str1, str1);
Vincent Robert
Thanks! That was exactly it. Now there's just one problem left... but that's another question.
Thanks