指针的数组符号

时间:2019-06-06 20:40:54

标签: c arrays pointers

我制作了一个函数,该函数返回指向新创建的矩阵的指针。现在,我希望该函数返回类型为status_t的错误代码,而不是指针。为此,必须添加另一个指针级别,并且必须通过引用返回矩阵。但是,我不明白为什么会出现细分错误。这是我的工作代码(a)和失败的尝试(b)的一部分:

(a)

int **create_matrix(size_t dimension) {
    int **p;
    size_t e;
    size_t h;

    if (dimension == 0)
        return NULL;

    for (h = 0; h < dimension; ++h) {
        if ((p[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free(p[e]);
                p[e] = NULL;
            } <-------- missing closing brace
            return NULL;
        }
    }
    return p;
}

(b)

status_t create_matrix(size_t dimension, int ***p) {
    size_t e;
    size_t h;

    if (p == NULL)
        return ERROR_NULL_POINTER;

    for (h = 0; h < dimension; ++h) {
        if (((*p)[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free((*p)[e]);
                (*p)[e] = NULL;
            } <-------- missing closing brace
            return ERROR_NO_MEMORY;
        }
    }
}

谢谢!

1 个答案:

答案 0 :(得分:4)

(a)并非完全“有效”:

一方面,它的{}多,因此甚至无法编译。您可能忘记了终止外部for循环。

int ** p;
...
    if ((p[h]=...))

这会在初始化之前取消引用p。使用未初始化变量的值是未定义的行为。您需要先为p分配一些内容(可能是通过动态分配另一个数组)。

要确定版本(b)是否存在相同的问题,我们必须查看调用代码,但猜测它也是UB。

内循环还有另一个问题:

        for (e = h; e >= 0; --e)

esize_t,它是无符号整数类型,因此条件e >= 0始终为真。

您使用什么编译器(和编译器选项)?有了gcc -Wall -Wextra -pedantic,我得到warnings for both of these

固定版本如下:

int **create_matrix(size_t dimension) {
    int **p = calloc(dimension, sizeof *p);
    if (!p) {
        return NULL;
    }

    for (size_t i = 0; i < dimension; i++) {
        if (!(p[i] = calloc(dimension, sizeof *p[i]))) {
            while (i--) {
                free(p[i]);
            }
            free(p);
            return NULL;
        }
    }

    return p;
}

然后可以将版本(b)定义为

status_t create_matrix_2(size_t dimension, int ***p) {
    if (!p) {
        return ERROR_NULL_POINTER;
    }
    if (!(*p = create_matrix(dimension))) {
        return ERROR_NO_MEMORY;
    }
    return SUCCESS_OR_SOMETHING;
}

我不确定您想要获得成功的回报是什么;您的版本(b)在那里缺少返回声明。