c语言 - 为什么编译器会发出警告,指出指针在初始化时可能未初始化,并且指针不会更新?


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的当前值?它们是不同的指针但是指向同一个内存块,这就是为什么!我说得对吗?

在本例中,ps再次指向同一内存。当您执行分配p[0] = 'e'时,您是在NOT更改ps——实际上您是在更改p所指向的值。而且,由于ps指向同一个内存,所以当您取消引用ps时,您所做的更改将是可见的。下面是一个深入的例子——我建议编译并运行它,看看打印出了什么,并阅读解释每一步发生的事情的评论。

#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将不同。

最新更新