Можно ли передавать (двойные ***) указатели, используя (void **)? - PullRequest
2 голосов
/ 30 апреля 2020

Я компилирую приведенный ниже код с помощью g cc, используя -Wall -Werror, и он компилируется чисто, работает как положено; Тем не менее, мне просто любопытно, если в контексте ANSI и / или ISO C все нормально, передавать указатель (double ***) через (void **).

ISO / IEC 9899: 2017 , раздел 6.6 - 9 гласит:

"Массив-индекс [] и доступ к элементу . и -> операторы, адрес & и однонаправленные * унарные операторы и приведение указателей могут использоваться при создании константы адреса, но значение объекта не должно быть доступ к ним осуществляется с помощью этих операторов. "

В связи с этой рекомендацией функция allocateMatrix фактически должна просто выделить память и вернуть соответствующий адрес; поэтому, пожалуйста, не обращайте внимания на внутренний l oop, который присваивает значения, он только для целей тестирования.

void allocateMatrix(int n, void **a) {
    int i = 0, j = 0;
    double **pTmp = calloc(n, sizeof(double *));

    for (i = 0; i < n; i++) {
        pTmp[i] = malloc(n * sizeof(double));

        // following loop is inserted to make sure code runs as expected
        // this does not exists in real code
        for (j = 0; j < n; j++) {
            pTmp[i][j] = (double)(i + 1) + (double)(j + 1) / 10.0f;
        }
    }

    *a = pTmp;
    return;
}

int main(int argc, char const *argv[]) {
    int i = 0, j = 0;
    int n = 5;
    double **a = NULL;

    // "a" is a (double **) pointer; so, "&a" is now a (double ***) pointer
    allocateMatrix(n, (void **)&a);

    // testing...
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%6.2lf", a[i][j]);
        }

        printf("\n");
    }

    return 0;
}

1 Ответ

4 голосов
/ 30 апреля 2020

Стандарт C допускает преобразование в void * и обратно, однако, что lattitute не существует для void **.

Измените аргумент функции на void * и приведите его соответствующим образом, и оно будет работать.

void allocateMatrix(int n, void *a) {
    ...
    *(double ***)a = pTmp;
}

И изменение удалите приведение из вызова функции:

allocateMatrix(n, &a);
...