c - 为什么编译器在将要初始化的指针可能未初始化并且指针不会更新时发出警告?
问题描述
char *s, *p = s;
size_t len = 0;
while (str[len++]);
s = malloc(sizeof(*s) * (len + 1));
How come here: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;
^
因为是一个指向 s 的指针,当它指向什么时候分配内存时,它p
不会被更新吗?p
s
s
为什么我必须这样做:
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
更新?
解决方案
Let's break this down a little.
What you have essentially is this:
char *s;
char *p = s;
s = malloc(...);
You're proposing that when s
gets initialized (by malloc
's return value), the value of p
should also update.
But, as you've discovered this is not the case. Initially, when you do char *s
, s
can point to anything. It is not yet initialized.
Subsequently, when you do char *p = s;
, you are assigning the current value of s
to p
-- which could be anything.
If you change the value of s
, that doesn't automatically change the value of p
. They are distinct variables. They are both pointers - but that doesn't mean they should point to the same thing just because one was initialized from the other.
There is no intrinsic link between these two pointers, even if you assign one to the other. The point is, even if they do point to the same thing at one point in time, you can change what one points to in the future without affecting the other.
Its actually no different from assigning to a non-pointer variable and asserting that it should be updated automatically, e.g.
int i;
int j;
i = j;
j = 5;
printf("%d\n", i); // Prints rubbish
printf("%d\n", j); // Prints 5
Here, j
is initialized and the printf
is as expected. Meanwhile, i
was initialized from j
's rubbish value -- the value that happened to be lying in memory at j
's location (and that could be anything). Yet, I doubt anyone would suggest that i
should "automatically" update in this case.
UPDATE:
The following update is in response to this followup comment made:
Here's why I thought it would update.. char *s = malloc(100); char *p = s; see this, right? p[0] = 'e' for example will also change s[0], so I thought that since if assigning the element of p by index would also change the element of s by index, there would be change/update, right? How come p[0] = 'e' changes the element of both s and p, even though p just assigned the current value of malloc? They are different pointers but point to the same memory block, that's why! Am I right?
In this example, p
and s
again point to the same memory. When you do the assignment p[0] = 'e'
, you are NOT changing p
or s
-- you are in fact changing the value pointed to by p
. And, since p
and s
point to the same memory, the change you've made will be visible through both p
and s
-- when you dereference either. Below is an in-depth example - I recommend compiling it and running it to see what gets printed, and read the comments which explain what is happening at each step.
#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;
}
推荐阅读
- python - 在 for 循环中识别要附加的列表中特定值的索引
- python-3.x - 如何使用 YouTube API 仅按用户名搜索?
- javascript - 使用全选或单独选择多个复选框
- java - Java递归方法将数组的索引设置为+1,然后调用-1
- java - 无法加载 io.micrometer.core.instrument.Timer$1
- r - 如何从图像中删除 tibble?
- security - Azure DevOps:拒绝向读者/项目有效用户查看“任务组”
- python - 更改等高线图上的颜色和标签的位置
- csv - 将 CSV 文件从 Google Drive 加载到 BigQuery 会产生零行且没有错误
- batch-file - 如何使用批处理文件脚本编辑 web.config 文件内容?