C:动态分配时通过引用传递
C: Passing by reference during dynamic allocaion
我的代码是分配和初始化数组如下(floatalloc2
是一个用于分配二维数组的函数):
#include <stdio.h>
#include <stdlib.h>
void alloc_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
G = floatalloc2(nx, nz);
switch (adjwfd){
case 1:
L1 = floatalloc2(nx, nz);
break;
case 2:
L2 = floatalloc2(nx, nz);
break;
}
}
void init_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
memset(G[0],0,nx*nz*sizeof(float));
switch (adjwfd){
case 1:
memset(L1[0],0,nx*nz*sizeof(float));
break;
case 2:
memset(L2[0],0,nx*nz*sizeof(float));
break;
}
}
int main(int argc, char *argv[])
{
int adjwfd_P=1, nx=10, nz=10;
float **glob=NULL, **local1=NULL, **local2=NULL;
alloc_arr(adjwfd_P, nx, nz, glob, local1, local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
exit(0);
}
编译通过。但是当我 运行 这段代码时,它出错了:
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
但是,我发现如果我按如下方式更改 alloc_arr
,它会 运行 成功:
#include <stdio.h>
#include <stdlib.h>
void alloc_arr(int adjwfd, int nx, int nz, float ***G, float ***L1, float ***L2)
{
*G = floatalloc2(nx, nz);
switch (adjwfd){
case 1:
*L1 = floatalloc2(nx, nz);
break;
case 2:
*L2 = floatalloc2(nx, nz);
break;
}
}
void init_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
memset(G[0],0,nx*nz*sizeof(float));
switch (adjwfd){
case 1:
memset(L1[0],0,nx*nz*sizeof(float));
break;
case 2:
memset(L2[0],0,nx*nz*sizeof(float));
break;
}
}
int main(int argc, char *argv[])
{
int adjwfd_P=1, nx=10, nz=10;
float **glob=NULL, **local1=NULL, **local2=NULL;
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
exit(0);
}
我的问题是为什么我必须取二维数组的地址,而在alloc_arr
中只为分配部分定义三维数组,而在其他函数如init_arr
中,我可以只将原始二维数组传递给函数吗?
发生这种情况是因为 scopes。
在您的 main
函数中定义:
// [...]
float **array = NULL;
Just a reminder that array
is a pointer to a pointer (a 2D array as you call it).
在 alloc_arr
函数中,您想更改 array
在主函数中 指向的位置。因此,您传递了对局部变量 array
的引用。这样 alloc_arr
函数就可以改变局部变量 array
.
一个更简单的例子:
void change_value(int *a)
{
*a = 42;
}
void cant_change_value(int a)
{
a = -21;
}
int main(void)
{
int a = 0;
// At this point a is 0
cant_change_value(a);
// a is still 0, because cant_change_value only modified the COPY of a
// that was passed to the function
change_value(&a);
// a is now 42, because the function change_value received the address of a
// and modified it's content
return (0);
}
回到您的示例,如果函数 alloc_arr
没有使用指向您的二维数组的指针,它将无法修改 main
函数中的指针。
This 很好地介绍了指针的工作原理。
PS:你的变量名应该更明确地说明它们是什么。 “adjwfd_P
”可能对您有意义,但对其他阅读您代码的人可能没有意义。
why I have to take the address of the 2D array, and in the alloc_arr define 3D array only for the allocation part,......
在这种情况下:
alloc_arr(adjwfd_P, nx, nz, glob, local1, local2);
您实际上将最后三个参数作为 NULL
传递给 alloc_arr()
函数参数 G
、L1
和 L2
作为 glob
, local1
和 local2
用 NULL
初始化,在 alloc_arr()
void alloc_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
G = floatalloc2(nx, nz);
.....
L1 = floatalloc2(nx, nz);
.....
L2 = floatalloc2(nx, nz);
.....
内存正在分配给 G
、L1
和 L2
,它们是 alloc_arr()
函数的 局部变量 。在main()
中,glob
、local1
和local2
在alloc_arr()
函数返回后仍然是空指针。这些空指针传递给 init_arr()
,当试图在 init_arr()
中访问它们时,您的程序出现分段错误。
在这种情况下
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
您正在将指针 glob
、local1
和 local2
的地址作为参数传递给 alloc_arr()
函数参数 G
、L1
和 L2
,这意味着 G
、L1
和 L2
将分别保存 glob
、local1
和 local2
指针的地址。
void alloc_arr(int adjwfd, int nx, int nz, float ***G, float ***L1, float ***L2)
{
*G = floatalloc2(nx, nz);
.....
*L1 = floatalloc2(nx, nz);
.....
*L2 = floatalloc2(nx, nz);
.....
取消引用指针 G
将得到 glob
指针,即 *G
是 glob
。同样,取消引用 *L1
和 *L2
将分别给出指针 local1
和 local2
。所以,当分配内存给*G
、*L1
和*L2
时,实际上会分配内存给glob
、local1
和local2
指针。
whereas in other functions such as init_arr, I can just pass the original 2D array into the function?
看看这个:
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
alloc_arr()
将内存分配给 glob
、local1
和 local2
,这意味着从 alloc_arr()
返回后(假设一切正常)指针 glob
、local1
和 local2
指向有效的内存位置。在 init_arr()
中,您只是将这些内存位置作为参数传递给 init_arr()
函数参数 G
、L1
和 L2
。在 init_arr()
中,访问 G
、L1
和 L2
意味着它正在访问这些内存位置。
附加:
遵循良好的编程习惯,确保在程序退出前释放分配的内存。
我的代码是分配和初始化数组如下(floatalloc2
是一个用于分配二维数组的函数):
#include <stdio.h>
#include <stdlib.h>
void alloc_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
G = floatalloc2(nx, nz);
switch (adjwfd){
case 1:
L1 = floatalloc2(nx, nz);
break;
case 2:
L2 = floatalloc2(nx, nz);
break;
}
}
void init_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
memset(G[0],0,nx*nz*sizeof(float));
switch (adjwfd){
case 1:
memset(L1[0],0,nx*nz*sizeof(float));
break;
case 2:
memset(L2[0],0,nx*nz*sizeof(float));
break;
}
}
int main(int argc, char *argv[])
{
int adjwfd_P=1, nx=10, nz=10;
float **glob=NULL, **local1=NULL, **local2=NULL;
alloc_arr(adjwfd_P, nx, nz, glob, local1, local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
exit(0);
}
编译通过。但是当我 运行 这段代码时,它出错了:
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
但是,我发现如果我按如下方式更改 alloc_arr
,它会 运行 成功:
#include <stdio.h>
#include <stdlib.h>
void alloc_arr(int adjwfd, int nx, int nz, float ***G, float ***L1, float ***L2)
{
*G = floatalloc2(nx, nz);
switch (adjwfd){
case 1:
*L1 = floatalloc2(nx, nz);
break;
case 2:
*L2 = floatalloc2(nx, nz);
break;
}
}
void init_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
memset(G[0],0,nx*nz*sizeof(float));
switch (adjwfd){
case 1:
memset(L1[0],0,nx*nz*sizeof(float));
break;
case 2:
memset(L2[0],0,nx*nz*sizeof(float));
break;
}
}
int main(int argc, char *argv[])
{
int adjwfd_P=1, nx=10, nz=10;
float **glob=NULL, **local1=NULL, **local2=NULL;
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
exit(0);
}
我的问题是为什么我必须取二维数组的地址,而在alloc_arr
中只为分配部分定义三维数组,而在其他函数如init_arr
中,我可以只将原始二维数组传递给函数吗?
发生这种情况是因为 scopes。
在您的 main
函数中定义:
// [...]
float **array = NULL;
Just a reminder that
array
is a pointer to a pointer (a 2D array as you call it).
在 alloc_arr
函数中,您想更改 array
在主函数中 指向的位置。因此,您传递了对局部变量 array
的引用。这样 alloc_arr
函数就可以改变局部变量 array
.
一个更简单的例子:
void change_value(int *a)
{
*a = 42;
}
void cant_change_value(int a)
{
a = -21;
}
int main(void)
{
int a = 0;
// At this point a is 0
cant_change_value(a);
// a is still 0, because cant_change_value only modified the COPY of a
// that was passed to the function
change_value(&a);
// a is now 42, because the function change_value received the address of a
// and modified it's content
return (0);
}
回到您的示例,如果函数 alloc_arr
没有使用指向您的二维数组的指针,它将无法修改 main
函数中的指针。
This 很好地介绍了指针的工作原理。
PS:你的变量名应该更明确地说明它们是什么。 “adjwfd_P
”可能对您有意义,但对其他阅读您代码的人可能没有意义。
why I have to take the address of the 2D array, and in the alloc_arr define 3D array only for the allocation part,......
在这种情况下:
alloc_arr(adjwfd_P, nx, nz, glob, local1, local2);
您实际上将最后三个参数作为 NULL
传递给 alloc_arr()
函数参数 G
、L1
和 L2
作为 glob
, local1
和 local2
用 NULL
初始化,在 alloc_arr()
void alloc_arr(int adjwfd, int nx, int nz, float **G, float **L1, float **L2)
{
G = floatalloc2(nx, nz);
.....
L1 = floatalloc2(nx, nz);
.....
L2 = floatalloc2(nx, nz);
.....
内存正在分配给 G
、L1
和 L2
,它们是 alloc_arr()
函数的 局部变量 。在main()
中,glob
、local1
和local2
在alloc_arr()
函数返回后仍然是空指针。这些空指针传递给 init_arr()
,当试图在 init_arr()
中访问它们时,您的程序出现分段错误。
在这种情况下
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
您正在将指针 glob
、local1
和 local2
的地址作为参数传递给 alloc_arr()
函数参数 G
、L1
和 L2
,这意味着 G
、L1
和 L2
将分别保存 glob
、local1
和 local2
指针的地址。
void alloc_arr(int adjwfd, int nx, int nz, float ***G, float ***L1, float ***L2)
{
*G = floatalloc2(nx, nz);
.....
*L1 = floatalloc2(nx, nz);
.....
*L2 = floatalloc2(nx, nz);
.....
取消引用指针 G
将得到 glob
指针,即 *G
是 glob
。同样,取消引用 *L1
和 *L2
将分别给出指针 local1
和 local2
。所以,当分配内存给*G
、*L1
和*L2
时,实际上会分配内存给glob
、local1
和local2
指针。
whereas in other functions such as init_arr, I can just pass the original 2D array into the function?
看看这个:
alloc_arr(adjwfd_P, nx, nz, &glob, &local1, &local2);
init_arr(adjwfd_P, nx, nz, glob, local1, local2);
alloc_arr()
将内存分配给 glob
、local1
和 local2
,这意味着从 alloc_arr()
返回后(假设一切正常)指针 glob
、local1
和 local2
指向有效的内存位置。在 init_arr()
中,您只是将这些内存位置作为参数传递给 init_arr()
函数参数 G
、L1
和 L2
。在 init_arr()
中,访问 G
、L1
和 L2
意味着它正在访问这些内存位置。
附加:
遵循良好的编程习惯,确保在程序退出前释放分配的内存。