让我们稍微分解一下。
你所拥有的基本上是这样的:
char *s;
char *p = s;
s = malloc(...);
您提议当s 被初始化(通过malloc 的返回值)时,p 的值也应该更新。
但是,正如您所发现的,情况并非如此。最初,当您执行char *s 时,s 可以指向任何东西。它尚未初始化。
随后,当您执行char *p = s; 时,您会将s 的当前 值分配给p——这可能是任何东西。
如果您更改s 的值,则不会自动更改p 的值。它们是不同的变量。它们都是指针——但这并不意味着它们应该指向同一个东西,因为它们是从另一个初始化的。
这两个指针之间没有内在联系,即使您将一个分配给另一个。关键是,即使它们在某个时间点确实指向同一事物,您也可以在将来更改其中一个指向的内容,而不会影响另一个。
它实际上与分配给非指针变量并断言它应该自动更新没有什么不同,例如
int i;
int j;
i = j;
j = 5;
printf("%d\n", i); // Prints rubbish
printf("%d\n", j); // Prints 5
这里,j 被初始化,printf 符合预期。同时,i 是从j 的垃圾值初始化的——该值恰好位于内存中j 的位置(可能是任何东西)。然而,我怀疑有人会建议 i 在这种情况下“自动”更新。
更新:
以下更新是针对此后续评论的回应:
这就是我认为它会更新的原因.. char *s = malloc(100);字符 *p
= s;看到这个,对吧?例如 p[0] = 'e' 也会改变 s[0],所以我认为如果通过索引分配 p 的元素也会
按索引更改 s 的元素,会有更改/更新,对吗?
p[0] = 'e' 怎么会同时改变 s 和 p 的元素,即使 p
刚刚分配了 malloc 的当前值?它们是不同的指针
但是指向同一个内存块,这就是为什么!我说的对吗?
在本例中,p 和 s 再次指向同一个内存。当您分配p[0] = 'e' 时,您不 更改p 或s - 实际上您更改了p 指向的值。而且,由于p 和s 指向同一个内存,因此您所做的更改将通过p 和s 可见——当您取消引用时。下面是一个深入的示例 - 我建议编译并运行它以查看打印的内容,并阅读解释每一步发生了什么的 cmets。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// this initializes s to point to some block of memory, e.g. address 0x560890f49260 when I run it locally
// it can store 100 bytes (chars) of data
char *s = malloc(100);
// this initializes p to point to the same block of memory as s => 0x560890f49260
char *p = s;
// this prints out the value of p and s
// they are of type 'pointer', so use %p
// this shows their address as being the same
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this sets the 1st byte at the location pointed to by p
// the thing we're changing is at address 0x560890f49260
// this "array" notation is just syntactic sugar for dereferencing a pointer - see below
p[0] = 'e';
// but p and s are unchanged
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this also changes the 1st byte (same as *p = 'e' and p[0] = 'e')
// here we're using the dereferencing syntax explictly
*(p + 0) = 'e';
// and p and s are still the same
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this changes the 2nd byte (same as p[1] = 'f')
// the thing we're changing is at address 0x560890f49261 - i.e. the next byte
*(p + 1) = 'f';
// and p and s still haven't changed
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this prints the 1st and 2nd byte pointed to by p and s
// they show the same thing in both cases - since p and s point to the same thing
printf("First byte pointed to by p: %c\n", p[0]);
printf("First byte pointed to by s: %c\n", s[0]);
printf("Second byte pointed to by p: %c\n", p[1]);
printf("Second byte pointed to by s: %c\n", s[1]);
// now p is pointing to something new, e.g. address 0x5617ba3ef6e0 when I run it locally
p = malloc(100);
// we see that p **HAS** changed, but s has **NOT** changed
// they are now pointing to different things
printf("This is where p points to: %p (new location!)\n", p);
printf("This is where s points to: %p (old location!)\n", s);
// this sets the 1st byte pointed to by p to be 'g'
p[0] = 'g';
// we can see that the 1st byte pointed to by p is 'g'
printf("First byte pointed to by p: %c\n", p[0]);
// while the first byte pointed to be s is unaffected
// since p and s point to different things
printf("First byte pointed to by s: %c\n", s[0]);
// always free your memory
free(p);
free(s);
return 0;
}