访问作为空指针段错误传递的int数组

时间:2018-12-15 09:08:10

标签: c arrays pointers segmentation-fault void-pointers

我在玩指针,偶然发现了这个问题。像在此question中一样,我想要函数foo的通用方法签名,因此我选择了void * input作为参数。出于测试原因,我将void指针强制转换为int **指针,以将其用作2D数组。

#include <stdio.h>
#include <stdlib.h>
void * foo(void *input, size_t mySize)
{
    for (size_t i = 0; i < mySize; ++i)
    {
        for (size_t j = 0; j < mySize; ++j)
        {
            ((int **)input)[i*mySize][j] = 10*i+j;
        }
    }
    return input;
}

int main(int argc, char const *argv[])
{
    size_t const mySize = 10;
    void * myMemory, * testPtr;

    myMemory = malloc(mySize * mySize * sizeof(int));

    testPtr = foo(myMemory, mySize);
    free(testPtr);
    return 0;
}

现在,我认为使用[]运算符与将int添加到指针相同,例如((int **)input[i][j]就像`(((int **)input)+ i + j

但是在foo segfaults中访问输入数组并使用gdb显示给我

(gdb) p ((int **)input)[i][j]
Cannot access memory at address 0x0
(gdb) p ((int **)input)+i+j
$25 = (int **) 0x405260

因此显然存在区别。因此,我很困惑。

2 个答案:

答案 0 :(得分:1)

您为一个一维数组分配了mySize * mySize元素。 int **是一个指向int的指针的数组,您想要的是

int **array2d;
int *p;
array2D = malloc(ROWS * sizeof(int*) + ROWS * COLUMNS * sizeof(int));
p = (int*) &array2d[ROWS];
for (size_t i = 0; i < ROWS; ++i)
    array2d[i] = &p[i * COLUMNS];

现在array2d [row] [column]可以工作了。

或者,正如已经建议的那样,使用一维数组并使用array [row * COLUMNS + column]公式。

答案 1 :(得分:1)

虽然数组和指针相似,但它们并不相同。

一个数组(一维或多维)描述了一个连续的内存块,其中包含特定的数据类型。例如,int arr [10]声明arr为内存中的10个连续intint multi_arr[5][10]multi_arr声明为内存中10个连续int的5个数组。

此外,名称arr是此数组的基地址,将其传递给函数将与传递&arr[0]相同。

但这就是相似之处结束的地方。多维数组不能(技术上)强制转换为指向指针的指针,然后再次返回。

如果上面的arr指向int的一个块,那么取消引用int ** ptr的第一个维将导致您指向int的一个指针块。取消引用 that 不会像多维数组那样带您深入该块,而是可以指向任何地方。