void func(int *x) {
x = malloc(10);
}
int main() {
int *a ;
func(a);
return 0;
}
上面的代码,malloc会不会为a申请到空间?先说正确的写法:
void func(int **x) {
*x = malloc(10);
}
int main() {
int *a ;
func(&a);
return 0;
}
那为什么会这样呢?让我们来解释下原因吧
假设我们有一个整数变量a
,它存储在内存中的某个位置,我们可以假设这个位置的地址是0x100
。现在,我们创建了一个指针变量p
,并将a
的地址赋值给p
,所以p
存储的地址是0x100
。此时,p
也存储在内存中的某个位置,我们可以假设这个位置的地址是0x200
。
int a = 10; // 假设a的地址是0x100
int *p = &a; // 假设p的地址是0x200,p存储的地址是0x100
现在,我们将p
作为参数传递给一个函数func
。在func
函数中,我们有一个新的指针变量x
,它接收了p
的值,所以x
存储的地址也是0x100
。但是,x
在内存中的位置是不同的,我们可以假设这个位置的地址是0x300
。
void func(int *x) { // 假设x的地址是0x300,x存储的地址是0x100
x = malloc(10); // x现在存储的是新分配的内存的地址,假设是0x400
}
func(p);
在func
函数中,我们为x
分配了新的内存,所以x
现在存储的地址是新分配的内存的地址,假设是0x400
。但是,这个改变并没有影响到p
,因为p
和x
在内存中的位置是不同的,即使它们存储的地址原本是相同的。所以,即使我们改变了x
存储的地址,p
存储的地址仍然是0x100
,并没有改变。
再说说为什么第二个函数就可以:
假设我们有一个整数指针a
,它存储在内存中的某个位置,我们可以假设这个位置的地址是0x100
。现在,我们创建了一个指向指针的指针p
,并将a
的地址赋值给p
,所以p
存储的地址是0x100
。此时,p
也存储在内存中的某个位置,我们可以假设这个位置的地址是0x200
。
int *a; // 假设a的地址是0x100
int **p = &a; // 假设p的地址是0x200,p存储的地址是0x100
现在,我们将p
作为参数传递给一个函数func
。在func
函数中,我们有一个新的指向指针的指针x
,它接收了p
的值,所以x
存储的地址也是0x100
。但是,x
在内存中的位置是不同的,我们可以假设这个位置的地址是0x300
。
void func(int **x) { // 假设x的地址是0x300,x存储的地址是0x100
*x = malloc(10); // x现在存储的是新分配的内存的地址,假设是0x400
}
func(p);
在func
函数中,我们为x
分配了新的内存,所以x
现在存储的地址是新分配的内存的地址,假设是0x400
。但是,这个改变也影响到了p
,因为p
和x
存储的是同一个地址,所以当我们通过x
改变这个地址时,p
存储的地址也会被改变。因此,即使我们改变了x
存储的地址,p
存储的地址也会改变,从0x100
变为0x400
。
这就是为什么在func
函数中,我们可以通过x
来改变a
的值。因为x
和a
都是指针,它们存储的是同一个地址,所以当我们通过x
改变这个地址时,a
的值也会被改变。