取消引用指向数组的指针

时间:2018-02-20 17:24:06

标签: c arrays pointers

我试图理解指针数组的指针是如何工作的。

我有以下结构

typedef struct Array {
    int capacity;
    int size;
    void **items;
} Array;

和以下函数为struct分配内存并返回指向它的指针

Array *createArray(int capacity) {
    Array *array = malloc(sizeof(Array *));
    array->capacity = capacity;
    array->size = 0;
    void **items = malloc(sizeof(void *) * array->capacity *  sizeof *items);
    if(items == NULL) {
        exit(1);
    }
    array->items = items;
    return array;
}

现在,我想初始化一个指向此结构的指针数组。我就是这样做的

Array *(*createHashTable(int size))[10] {
    Array *array[10]; 
    int i = 0;
    for(i = 0; i < size; i++) {
        array[i] = createArray(size);
    }
    Array *(*ptr)[10] = &array;
    for(i = 0; i < size; i++) {
        printf("%d\n", (*(ptr[0] + i))->capacity);
    }
    return ptr;
}

print语句给出了我的期望:

10
10
10
10
10
10
10
10
10
10

现在,我的主要功能

int main(int argc, char *argv[]) {
    Array *(*ptr)[10] = createHashTable(10);
    printf("%d\n", (*(ptr[0]+9))->capacity);
    return 0;
}

到目前为止,一切对我都有意义,main中的printf语句正常工作。然而,令我困惑的部分是我在main函数中放置一个for循环,如此

int main(int argc, char *argv[]) {
    Array *(*ptr)[10] = createHashTable(10);
    int i = 0;
    for(i = 0; i < 10; i++) {
        printf("%d\n", (*(ptr[0] + i))->capacity);
    }
    return 0;
}

我得到以下输出,

10
10
Segmentation fault: 11

为什么我的程序只在我循环时才会出错?我是否遗漏了一些关于返回指向指针数组的指针的基本知识?

2 个答案:

答案 0 :(得分:2)

<强>第一即可。问题似乎是你没有分配足够的内存,

Array *array = malloc(sizeof(Array *));

仅分配sizeof(void *)字节,并且可能小于sizeof(Array) 1

因此,当您尝试初始化返回的array时,您正在访问未分配的内存,从而调用未定义的行为。

要始终使用大量内存,请使用以下语法

Array *array = malloc(sizeof(*array));

这样可以确保分配正确的大小。

<强>第二即可。如果您看到值按预期打印,请将其归咎于未定义的行为。因为你的代码已经调用了它,所以它不会在你执行之后消失,并且问题将会出现得更早,更晚或者永远不会出现,但它仍然存在。这是关于未定义行为的最糟糕的事情,因为它未定义,你无法预测它何时或是否会发生。

1 事实上,它确实少了,因为你至少需要sizeof(void *) + 2 * sizeof(int),就是你忽略了填充。

答案 1 :(得分:1)

Array *array = malloc(sizeof(Array *));

应该是

Array *array = malloc(sizeof(Array));

sizeof(Array *)只是指针的大小,而sizeof(Array)是结构Array的大小。

但我不确切知道您的代码中发生了什么,因为我的计算机array->items = items;出现了问题,也许您可​​以尝试printf("%d\n", &((*(ptr[0]+9))->capacity));获取地址并找出确切的结果在此地址中显示gdb