在我认为我已经理解它们是如何工作之后,我尝试了这个:
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
指针的值(如str1,str2)是内存地址。当您转到该地址时,您将到达存储对象的内存中的“区域”。
但是:当我将str2分配给str1时,str1应该具有str2引用的同一对象的内存地址作为值,对吧?这里奇怪的是,指针的值保持不变(bfffd3cc内存地址),该地址后面的东西会发生变化。这对我来说实际上是完全没有逻辑的;)因为我认为内存地址是对象(或者内存块中对象的主页,无论如何)。所以我期待这个:
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
否则,我仍然没有明白这一点。 “指针变量”的值与“实际值”之间的关系,可以说是位于该存储器地址后面的对象。
答案 0 :(得分:9)
请记住,指针变量本身就是一个变量,所以它有一个地址。因此&str1
会产生指针变量的地址,而str1
是一个表达式,它会导致指针变量所持有的内容 - 它所指向的对象的地址。
假设:
然后你的指针看起来像这样:
初始化时:
str1
0xbfffd3c8 +---------------+
| |
| 0x00000100 |
| ("one") |
+---------------+
str2
0xbfffd3cc +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
=======================================
str1 = str2;
分配后:
str1
0xbfffd3c8 +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
str2
0xbfffd3cc +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
答案 1 :(得分:2)
您正在打印指针的引用,这是指针的地址,而不是指针的值。
答案 2 :(得分:2)
&str1
获取指针的地址。
好的,还记得我们怎么说所有的东西都“活着”在记忆中的某个地址?并且指针只是数字,一个数字是地址?
好的指针也是如此,因此他们有地址。
打印出&str1
时,打印出指针占用的内存。当你打印str1
时,你打印出指针的值,它是指向的内存地址。
当您打印*str1
时,您将取消引用指针,并打印 打印指向的值。
顺便说一句,好的工作:我已经阅读了你的最后两个问题,而且你已经阅读了这些问题,还有你的信用编写代码来证明或反驳你的理解是正确的。这正是你应该做的,而你正走在正确的轨道上。
你遇到的部分问题是字符串是有趣的东西,因为字符串实际上是一个(const)字符数组,而像NSLog这样的函数被编写为通常使用指向char的指针,这是打印字符串。给定一个指向字符串的指针,它实际上是循环的:取消引用指针,打印指向的字符,向指针添加一个,打印下一个字符,直到指向的字符是值为0的特殊字符,此时它找到了字符串的结尾并停止打印字符。
如果使用int和指向int的内容,您可能会发现所有这些都更容易理解。
答案 3 :(得分:1)
str1
是指向NSString
值的指针。
&str1
表示:str1
变量的地址。这是双重间接。
我想你想要值的地址,即str1
本身,而不是&str1
。
我们假设包含NSString
的{{1}}对象值位于地址@"one"
,而0x12345678
位于@"two"
。
最初0x1234ABC0
的值为str1
,0x12345678
的值为str2
。
这两个值分别存储在地址0x1234ABC0
和0xbfffd3cc
的内存中。这些是0xbfffd3c8
和str1
变量的地址,即str2
和&str1
的值。
当您撰写&str2
时,分配会将str1 = str2
的值更改为str1
的值,即str2
的值为str1
}。这是0x1234ABC0
对象的地址。但@"two"
变量(str1
)的地址不会更改。
答案 4 :(得分:1)
事实上,指针是一个带有专用算术的整数(IIRC,保证sizeof(int)== sizeof(void *))
如果您引用指针,您将获得存储它的地址;如果变量是自动的,那么你将获得存储指针的堆栈中的地址:这就是你获得这些结果的原因。
赋值行为类似于整数之间的赋值;事实上:
#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);
}
打印:
:~$ ./a.out
80484f8
80484fd
80484fd
答案 5 :(得分:1)
Objective-C中的对象使用指针。因此,为了处理您的NSString对象,您必须使用指向它的指针。这就是str1是指向NSString对象的指针。
如果要向NSString发送消息,可以使用语法[str1 doSomething]。
如果要打印字符串,则必须将指针传递给NSLog并告诉NSLog指针指向NSString,这由格式化规则“%@”完成。
现在,如果你只想打印str1指向的地址,你仍然必须传递指针str1但是你必须告诉NSLog你使用格式化规则“%x”将它打印为十六进制值。 / p>
这样的东西应该打印出你想要的东西:
// First print str1 as an hexadecimal value
// Then print the content of the NSString object str1 points to
NSLog(@"str1: %x, %@", str1, str1);