在这个玩具代码示例中:
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&amp; someArray会给我所需的数组(指向第一个元素的指针),并且在该数组上使用括号数组元素访问将为我提供所需的必要位置被分配。但是,我无法弄清楚为什么我会遇到段错误。
非常感谢!
答案 0 :(得分:3)
我想填充数组someArray,并在函数外部保留更改。
将数组传递给函数,因为它衰减到指向第一个元素的指针:
void fillArray(int* someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
someArray[i] = blah[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<MAX; i++) /* or memcpy() instead of loop */
(*someArray)[i] = blah[i];
}
}
并调用:
int* someArray = NULL;
fillArray(&someArray, blah);
free(someArray);
答案 1 :(得分:1)
当你创建一个数组时,例如int myArray [10] [20],从堆栈中分配一个保证连续的内存块,并使用普通数组算法来查找数组中的任何给定元素。
如果要从堆中分配该3D“数组”,可以使用malloc()并获取一些内存。记忆是“愚蠢的”。它只是一块记忆,应该被认为是一个载体。阵列附带的导航逻辑都没有附带,这意味着你必须找到另一种方法来导航你想要的3D阵列。
由于你对malloc()的调用返回一个指针,你需要的第一个变量是一个指向int * s向量的指针,你需要保存一些实际的整数数据IE:
int * pArray;
...但这仍然不是您要存储整数的存储空间。你拥有的是一个指针数组,目前指向什么都没有。要获取数据的存储空间,需要调用malloc()10次,每个malloc()在每次调用时为20个整数分配空间,其返回指针将存储在指针的* pArray向量中。这意味着
int * pArray
需要更改为
int ** pArray
正确地指示它是指针向量基础的指针。
第一个解除引用,* pArray [i],在一个int指针数组中找到你的位置,第二个解除引用,* p [i] [j],将你置于一个int内部的某个位置,指向一个pArray [i]中的int指针。
IE:你有一堆散布在整个堆中的整数向量,指向一组指针,跟踪它们的位置。完全不同于从堆栈静态分配的Array [10] [20],它是所有连续的存储,并且在任何地方都没有单个指针。
正如其他人所暗示的那样,基于指针的堆方法乍一看似乎并不是很有用,但结果却大有优势。
第1,最重要的是,你可以free()或realloc()来随时调整堆内存的大小,并且当函数返回时它不会超出范围。更重要的是,有经验的C编码器安排其功能在可能的情况下对向量进行操作,其中在函数调用中去除1级间接。最后,对于大型阵列,相对于可用内存,尤其是大型共享机器,大块连续内存通常不可用,并且对需要内存操作的其他程序不友好。在堆栈上分配的具有大型静态数组的代码是维护噩梦。
在这里你可以看到该表只是一个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;
}
答案 2 :(得分:0)
没有“数组/指针”等价,数组和指针是非常不同的。永远不要混淆他们。 someArray
是数组。 &someArray
是指向数组的指针,类型为int (*)[MAX]
。该函数接受一个指向指针的指针,即int **
,它需要指向存储器中某处的指针变量。代码中的任何位置都没有指针变量。它可能指向什么?
对于某些表达式中的第一个元素,数组值可以隐式降级成指针 rvalue 。需要左值的东西,比如取地址(&
)显然不会这样。以下是数组类型和指针类型之间的一些区别:
sizeof
是组件类型大小的长度;指针的sizeof
只是a的大小
指针