views:

186

answers:

3

I thought an variable in objective-c is just a reference to an object somewhere in memory. So for my understanding, the result must have been "one", because at the end i assign the object's memory address of str1 to str2, and previously I had assignend the memory adress of str2 to test.

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];

test = str2; // test is an instance variable. I use no getter/setter here! just for testing!
str2 = str1;
NSLog(test); // = "two" ??
+7  A: 

This is how pointers work. The result you see is normal and correct.

Let's list all of your variables and what strings they point to in memory as they are declared:

str1 -> "One"
str2 -> "Two"

Then, you execute some assignment instructions:

test = str2;

This assigns the value of the pointer str2 to test. So the pointers are

str1 -> "One"
str2 -> "Two"
test -> "Two"

Then

str2 = str1;

Assigns the value of the pointer str1 to str2. Now the pointers are

str1 -> "One"
str2 -> "One"
test -> "Two"

Then you print test, which is pointing to what str2 was pointing to originally, which is "Two".

I think you think that since you assigned str2 to the value of str1, and test to the value of str2, that the value of str1 somehow cascades into test. This is not the case. Once test's value is assigned, the information regarding where that value came from is lost. If you want test's value to be the same as str1's, you have you reverse the order of your assignment operations:

str2 = str1;
test = str2;
Welbog
Thnaks. I thing i've got that now. So those pointers always return the value, and not the memory adress of the object itself?
Thanks
Well, no. The value of the variable is an address, like you think. It's just that there is no "cascade" of assignments.
Welbog
+1 for clear illustration
Martin Peck
A: 

You have this:

test = str2; // test is an instance variable.testing!
str2 = str1;
NSLog(test); // = "two" ??

Now, let's pretend all those variables were ints.

On the first line, variable test is set to the value of variable str2. On the second line, variable str2 is set to the value of variable str1. On the third line, we print out the value of test, and it's indeed the value that str2 was when we assigned str2 to test. It really doesn't matter at all that we subsequently assigned str2 a different value.

Ok, but the variables are really pointers, you say, not ints.

No matter: think of a pointer as just a number, the address of somewhere in memory. And passing that to NSLog makes NSLog print not the value of the pointer, but the value of what the pointer points to, which is an array of char.

tpdi
Thanks. So it would be right to say, that the value of an variable always is an memory adress? and at the "location" of that adress is the actual value, or object, or whatever?
Thanks
No, that's only true for pointers.
tpdi
Or another try: Variables always point to an memory adress. Behind an memory adress always is an specific value or object. Is that right?
Thanks
Another Q: Every time I work with objects, my variables that represent them are "pointers", right?
Thanks
No, only pointers point to a memory address. An int, for example, doesn't. An object variable may be a pointer.
tpdi
When I look in XCode debugger, an int var shows up the value in "value", and an object var (pointer) shows something like an memory adress in "value". I think the light bulp is getting brighter a little bit now ;)
Thanks
Yes, because the value of a pointer is a memory address. Thus, getting back to your original question, when you assign a pointer to another pointer (test = str2), you're copying the memory address.
tpdi
A: 

A variable is a container. The assignment takes whatever's on the right side and puts it also in whatever's on the left side. In other words, it copies the value from one variable to the other; in this case, those values are pointers (memory addresses).

So here's what you did:

  1. Take the address that's in the str2 variable and put the same address in the test variable.
  2. Take the address that's in the str1 variable and put the same address in the str2 variable.

Step 2 doesn't affect the test variable; your only assignment to that variable was in step 1.

Important: You're not copying what's at the address; you're copying the address itself. There's still only one “two” string, but between steps 1 and 2, the address of that object is in both str2 and test. Then, in step 2, you replace the address in str2 with the address of the “one” string, which also exists in str1, leaving test as the only variable that still holds the address of the “two” string.

BTW, stringWithCString: is deprecated. Use stringWithUTF8String: or stringWithCString:encoding: instead.

Peter Hosey