char *s, *p = s;
size_t len = 0;
while (str[len++]);
s = malloc(sizeof(*s) * (len + 1));
原因:char *s, *p = s;
发出警告,但s
稍后将用malloc
初始化。
chl/string.c:9:15: warning: ‘s’ may be used uninitialized in this function [-Wmaybe-uninitialized]
9 | char *s, *p = s;
^
由于p
是一个指针,指向s,那么当s
将被分配内存时,当它指向s
时,p
不会也被更新吗?
为什么我必须这样做:
char *s, *p;
size_t len = 0;
while (str[len++]);
s = malloc(sizeof(*s) * (len + 1));
p = s;
我认为指针可以更改为它所指向的内容,那么为什么p
不作为指针更新呢?或者,如果我看错了,为什么我不能只做*p = s
,因为s
很快就会被初始化,而p
会指向s
,所以p
不会也更新吗?
让我们把它分解一下。
你基本上拥有的是:
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("%dn", i); // Prints rubbish
printf("%dn", 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'
时,您是在NOT更改p
或s
——实际上您是在更改p
所指向的值。而且,由于p
和s
指向同一个内存,所以当您取消引用p
和s
时,您所做的更改将是可见的。下面是一个深入的例子——我建议编译并运行它,看看打印出了什么,并阅读解释每一步发生的事情的评论。
#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: %pn", p);
printf("This is where s points to: %pn", 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: %pn", p);
printf("This is where s points to: %pn", 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: %pn", p);
printf("This is where s points to: %pn", 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: %pn", p);
printf("This is where s points to: %pn", 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: %cn", p[0]);
printf("First byte pointed to by s: %cn", s[0]);
printf("Second byte pointed to by p: %cn", p[1]);
printf("Second byte pointed to by s: %cn", 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: %cn", 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: %cn", s[0]);
// always free your memory
free(p);
free(s);
return 0;
}
哦,不,p不是指向s。
您的声明:
char *p = s;
它在说"将指针s的值复制到指针p〃中;,因此,无论存储在s中的地址是什么(它没有初始化(,它都将是存储在p中的值。
一旦s被分配了malloc的值,p将保持初始值,s将不同。