变量、指针、目的和存储地址:我为什么得到这个奇怪的结果?
-
03-07-2019 - |
题
之后,我认为我已经理解他们是如何工作的,我试图这样的:
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存的地址),这里的事情后,地址变更。这实际上完全unlogical我),因为我认为,存的地址是对象(或家庭的目的在存储器砖,什么都).所以我期望这样的:
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
否则,我仍然没有得到这一点。之间的关系的价值"的指针可变"和"实际值",可以说的对象的坐在后面,存的地址。
解决方案
记住这一指针的变量是一个可变自己,因此它具有一个地址。所以 &str1
结果,在该地址的指针可变的, str1
是一个表达结果的任何指针可变的是保持地址的对象的指示。
假设:
- 对象保持NSString"一"是在地址0x00000100
- 对象保持NSString"两个"是在地址0x00000200
然后你的指针可能看起来是这样的:
在初始化:
str1
0xbfffd3c8 +---------------+
| |
| 0x00000100 |
| ("one") |
+---------------+
str2
0xbfffd3cc +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
=======================================
后 str1 = str2;
分配:
str1
0xbfffd3c8 +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
str2
0xbfffd3cc +---------------+
| |
| 0x00000200 |
| ("two") |
+---------------+
其他提示
您正在打印指针的引用,这是指针的地址,而不是指针的值。
& str1
获取指针的地址。
好的,记住我们怎么说所有事情都“生活”了在记忆中的某个地址?并且指针只是数字,一个数字是地址?
好的指针也是如此,因此他们有地址。
打印& str1
时,打印出指针占用的内存。当你打印出 str1
时,你打印出指针的值,它是指向的内存地址。
当您打印 * str1
时,您将取消引用指针,并打印 打印指向的值。
顺便说一句,好的工作:我已经阅读了你的最后两个问题,而且你已经阅读了这些问题,还有你的信用编写代码来证明或反驳你的理解是正确的。这正是你应该做的,而你正走在正确的轨道上。
你遇到的部分问题是字符串是有趣的东西,因为一个字符串实际上是一个(const)字符数组,而像NSLog这样的函数被编写为通常使用指向char的指针,这是打印字符串。给定一个指向字符串的指针,它实际上是循环的:取消引用指针,打印指向的字符,向指针添加一个,打印下一个字符,直到指向的字符是值为0的特殊字符,此时它找到了字符串的结尾并停止打印字符。
如果使用int和指向int的内容,您可能会发现所有这些都更容易理解。
事实上,指针是一个带有专用算术的整数(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
str1
是指向 NSString
值的指针。
&amp; str1
表示: str1
变量的地址。这是双重间接。
我想你想要值的地址,即 str1
本身,而不是&amp; str1
。
假设包含 @“one”
的 NSString
对象值位于地址 0x12345678
和 @“two” ;
位于 0x1234ABC0
。
最初 str1
的值是 0x12345678
, str2
的值是 0x1234ABC0
。
这两个值分别存储在存储器 0xbfffd3cc
和 0xbfffd3c8
中。这些是 str1
和 str2
变量的地址,即&amp; str1
和&amp; str2
的值。
当您编写 str1 = str2
时,赋值将 str1
的值更改为与 str2
的值相同,即,值然后 str1
是 0x1234ABC0
。这是 @&quot; two&quot;
对象的地址。但 str1
变量( 0xbfffd3cc
)的地址不会改变。
Objective-C中的对象使用指针。因此,为了处理您的NSString对象,您必须使用指向它的指针。这就是str1是指向NSString对象的指针。
如果要向NSString发送消息,可以使用语法[str1 doSomething]。
如果要打印字符串,则必须将指针传递给NSLog并告诉NSLog指针指向NSString,这由格式化规则“%@”完成。
现在,如果您只想打印str1指向的地址,您仍然必须传递指针str1但是您必须告诉NSLog您使用格式化规则“%x”将其打印为十六进制值。
这样的东西应该打印出你想要的东西:
// First print str1 as an hexadecimal value
// Then print the content of the NSString object str1 points to
NSLog(@"str1: %x, %@", str1, str1);