C指针帮助:数组/指针等效

在这个玩具代码示例中:

int MAX = 5; void fillArray(int** someArray, int* blah) { int i; for (i=0; i<MAX; i++) (*someArray)[i] = blah[i]; // segfault happens here } int main() { int someArray[MAX]; int blah[] = {1, 2, 3, 4, 5}; fillArray(&someArray, blah); return 0; } 

…我想填充数组someArray,并在函数外部保留更改。

这是一个非常大的家庭作业的一部分,这个问题解决了这个问题,而不允许我复制解决方案。 我得到一个函数签名,接受一个int **作为参数,我应该编写逻辑来填充该数组。 我的印象是fillArray()函数中的dereferencing&someArray会给我所需的数组(指向第一个元素的指针),并且使用该数组上的括号数组元素访问将为我提供需要分配的必要位置。 但是,我无法弄清楚为什么我会遇到段错误。

非常感谢!

我想填充数组someArray,并在函数外部保留更改。

只需将数组传递给函数,因为它会衰减到指向第一个元素的指针:

 void fillArray(int* someArray, int* blah) { int i; for (i=0; i 

并调用:

 fillArray(someArray, blah); 

元素的更改将在函数外部显示。

如果实际代码是在fillArray()分配一个数组,则需要一个int**

 void fillArray(int** someArray, int* blah) { int i; *someArray = malloc(sizeof(int) * MAX); if (*someArray) { for (i=0; i 

并调用:

 int* someArray = NULL; fillArray(&someArray, blah); free(someArray); 

当你创建一个数组,比如int myArray [10] [20]时,从堆栈中分配一个保证连续的内存块,并使用普通数组算法来查找数组中的任何给定元素。

如果要从堆中分配该3D“数组”,可以使用malloc()并获取一些内存。 记忆是“愚蠢的”。 它只是一块记忆,应该被认为是一个载体。 arrays附带的导航逻辑都没有附带,这意味着您必须找到另一种方法来导航您想要的3Darrays。

由于您对malloc()的调用返回一个指针,您需要的第一个变量是一个指针,用于保存int * s的向量,您需要保存一些实际的整数数据IE:

int * pArray;

…但这仍然不是您要存储整数的存储空间。 你拥有的是一个指针数组,目前指向什么都没有。 要获取数据的存储空间,需要调用malloc()10次,每个malloc()在每次调用时为20个整数分配空间,其返回指针将存储在指针的* pArray向量中。 这意味着

int * pArray

需要改为

int ** pArray

正确地指示它是指向指针向量的指针。

第一个解除引用,* pArray [i],在一个int指针数组中找到你的位置,第二个解除引用,* p [i] [j],将你置于一个int内部的某个地方,由int指针指向粒子arrays[i]中。

IE:你有一堆散布在整个堆中的整数向量,指向一组指针,跟踪它们的位置。 完全没有类似于从堆栈静态分配的Array [10] [20],这是所有连续的存储,并且在任何地方都没有单个指针。

正如其他人所想到的那样,基于指针的堆方法乍一看似乎没有太大的用处,但事实certificate它非常优越。

首先,您可以随时使用free()或realloc()来调整堆内存大小,并且在函数返回时它不会超出范围。 更重要的是,有经验的C编码器安排其function在可能的情况下对向量进行操作,其中在函数调用中去除1级间接。 最后,对于大型arrays,相对于可用内存,尤其是大型共享机器,大块连续内存通常不可用,并且对需要内存操作的其他程序不友好。 在堆栈上分配的具有大型静态数组的代码是维护噩梦。

在这里你可以看到表只是一个shell收集从向量操作返回的向量指针,其中所有有趣的事情都发生在向量级或元素级。 在这种特殊情况下,VecRand()中的向量代码是calloc()它自己的存储并返回calloc()返回指向TblRand()的指针,但是TblRand也可以灵活地分配VecRand()的存储,只需通过调用calloc()将NULL参数替换为VecRand()

 /*-------------------------------------------------------------------------------------*/ dbl **TblRand(dbl **TblPtr, int rows, int cols) { int i=0; if ( NULL == TblPtr ){ if (NULL == (TblPtr=(dbl **)calloc(rows, sizeof(dbl*)))) printf("\nCalloc for pointer array in TblRand failed"); } for (; i!=rows; i++){ TblPtr[i] = VecRand(NULL, cols); } return TblPtr; } /*-------------------------------------------------------------------------------------*/ dbl *VecRand(dbl *VecPtr, int cols) { if ( NULL == VecPtr ){ if (NULL == (VecPtr=(dbl *)calloc(cols, sizeof(dbl)))) printf("\nCalloc for random number vector in VecRand failed"); } Randx = GenRand(VecPtr, cols, Randx); return VecPtr; } /*--------------------------------------------------------------------------------------*/ static long GenRand(dbl *VecPtr, int cols, long RandSeed) { dbl r=0, Denom=2147483647.0; while ( cols-- ) { RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF; r = sqrt(-2.0 * log((dbl)(RandSeed/Denom))); RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF; *VecPtr = r * sin(TWOPI * (dbl)(RandSeed/Denom)); VecPtr++; } return RandSeed; } 

没有“数组/指针”等价,数组和指针是非常不同的。 永远不要混淆他们。 someArray是一个数组&someArray是一个指向数组指针,其类型为int (*)[MAX] 。 该函数接受一个指向指针的指针,即int ** ,它需要指向内存中某处的指针变量。 代码中的任何位置都没有指针变量。 它可能指向什么?

在某些表达式中,数组值可以隐式降级为其第一个元素的指针rvalue 。 需要左值的东西,比如取地址( & )显然不会这样。 以下是数组类型和指针类型之间的一些区别:

  • 无法分配或传递数组类型。 指针类型可以
  • 指向数组的指针和指向指针的指针是不同的类型
  • 数组数组和指针数组是不同的类型
  • 数组类型的sizeof是组件类型大小的长度; 指针的sizeof就是指针的大小