在此代码中,当gdb
被分配时,依赖p
,0x602010
从0x0
更改为NULL
,(正如我所料)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 10;
// gdb output
int *p = (int *) malloc(sizeof(int)); // p = (int *) 0x602010
p = NULL; // p = (int *) 0x0
p = &a; // p = p = (int *) 0x7fffffffe15c
return 0;
}
但是,当p
在main()
之外的task()
之外更改时,我猜它不会更改为0x0
而我不会这样做:
#include<stdio.h>
#include<stdlib.h>
void tast(int *p);
void task(int *p)
{
/*
before
(gdb) p p
$1 = (int *) 0x7fffffffe15c (same as variable a)
(gdb) p &p
$2 = (int **) 0x7fffffffe128
*/
p = NULL;
/*
after
(gdb) p p
$3 = (int *) 0x7fffffffe15c no change?
(gdb) p &p
$4 = (int **) 0x7fffffffe128
*/
}
int main()
{
int a = 10;
// gdb output
int *p = (int *) malloc(sizeof(int)); // p = (int *) 0x602010
p = NULL; // p = (int *) 0x0
p = &a; // p = p = (int *) 0x7fffffffe15c
// it is possible to change what p points to
// after calling task()?
task(p);
// p will be NULL?
return 0;
}
为什么p在task()中没有变为0x0?
答案 0 :(得分:2)
指针是一个值,就像int
一样。可以这样想:如果你将int
传递给task()
并在task
函数内部进行了更改,那么它会发生变化吗?不,因为变量是按值传递的。
当您调用task
时,您正在将该值的副本(在本例中为指针)传递给该函数。你想要做的是改变指针的值,这意味着你需要一个指向存储值的位置的指针。这是指向指针int **
。
代替:
void task(int **p)
{
*p = NULL;
}
和
task(&p);
传递p *
的位置。
另一个例子,这次使用int
,这可能会更清楚。
void makeTen(int *valuePointer)
{
// Change the variable that valuePointer is pointing to.
*valuePointer = 10;
}
void demoFunction()
{
int x = 5;
// x == 5
// Call this with a pointer to the variable X.
// We are passing the memory address of the variable x.
makeTen(&x);
// x == 10
}
如果您理解这一点,请将int
更改为int *
,您将了解原始问题。
答案 1 :(得分:1)
在第一个片段中,当你为malloc指针指定NULL时,你正在泄漏内存。
在第二个片段中,您将指针传递其值。所以这些变化不会反映在主要方面。 This explains the problem.
答案 2 :(得分:0)
如果在传递指针后期望main中的p == NULL
,则需要将指针传递给指针。例如
void task(int** p)
{
*p = NULL;
}
并传递
task(&p);
此外,您应该注意此代码泄漏。在free(p)
来电之后设置p = NULL
之前,您应该malloc
。
答案 3 :(得分:0)
因为您误将指针地址及其指向的对象误认为。
void task(int *p)
{
p = NULL;
}
此函数将获取指向int的指针,因此,您可以修改存储在其他位置的int值。但是,int值的变量的地址是按值传递的。这意味着,地址存储在本地。将“NuLL”分配给局部变量并不是您想要的。
如果您将其更改为:
void task(int **p)
{
*p = NULL;
}
您将获得指向int的指针。现在也指出了地址,您可以从代码中更改它。指向int的指针必须通过引用传递(这是你的情况)。