Растущие массивы.Обращайтесь к элементам по указателям, а не по индексам - PullRequest
0 голосов
/ 28 февраля 2019

Поскольку адрес массива может изменяться при перераспределении памяти, основная часть программы (в теле функции main ()) должна ссылаться на элементы по индексам, а не по указателям.Зачем?Можете ли вы показать пример доступа к элементам с помощью указателей?(Извините за мой английский).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Nameval Nameval;

struct Nameval {
    char *name;
    int value;
};

struct NVtab {
    int nval;         /* current number of values */ 
    int max;          /* allocated number of values */
    Nameval *nameval; /* array of name-value pairs */
};

enum {NVINIT = 1, NVGROW = 2};

/* addname: add new name and value to nvtab */
int addname(struct NVtab *nvtab, Nameval newname) {
    Nameval *nvp;
    if (nvtab->nameval == NULL) { /* first time */
        nvtab->nameval = (Nameval *) malloc(NVINIT * sizeof(Nameval));
        if (nvtab->nameval == NULL) 
            return -1;
        nvtab->max = NVINIT;
        nvtab->nval = 0;
    } else if (nvtab->nval >= nvtab->max) { /* grow */
        nvp = (Nameval *) realloc(nvtab->nameval,
                                  (NVGROW*nvtab->max)*sizeof(Nameval));
        if (nvp == NULL)
            return -1;
        nvtab->max *= NVGROW;
        nvtab->nameval = nvp;

    }
    nvtab->nameval[nvtab->nval] = newname;
    return nvtab->nval++;
}

int main(void) {
    struct NVtab nvtab = {0, 0, NULL};

    int curnum;
    curnum = addname(&nvtab, (Nameval) {.name="Andy", .value=12});
    printf("%d\n", curnum);
    curnum = addname(&nvtab, (Nameval) {.name="Billy", .value=18});
    printf("%d\n", curnum);
    curnum = addname(&nvtab, (Nameval) {.name="Jack", .value=71});
    printf("%d\n", curnum);
    for (int i = 0; i < nvtab.nval; i++) {
        printf("%s %d\n", nvtab.nameval[i].name,
                          nvtab.nameval[i].value);
    }
}

Например, почему мы не можем отобразить массив следующим образом:

for (int i = 0; i < nvtab.nval; i++)
    printf("%s %d\n", nvtab.*(nameval+i).name, nvtab.*(nameval+i).value);

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Вы не должны назначать указатель, рассчитанный для определенного индекса, переменной с продолжительностью хранения, которая может превышать операцию вставки.

Этот указатель может стать недопустимым, поэтому уроком этого примера являетсявсегда переоценивайте итераторы для динамических структур данных.

Например, что не сделать:

auto *foo = &nvtab.nameval[i];
addname(&nvtab, (Nameval) {.name="Billy", .value=18});
printf("%s %d\n", foo->name, foo->value);

В последней строке это может работатьили сбой.В зависимости от того, realloc переместил выделение или изменил размер на месте.За исключением того, что вы никогда не узнаете наверняка, пока не выполните его, поскольку он даже не является полностью детерминированным.

0 голосов
/ 28 февраля 2019

Это недопустимый синтаксис:

nvtab. *(nameval+i).name

Оператор доступа к члену . ожидает, что за ним последует имя участника.То, что вы хотите:

 (*(nvtab.nameval+i)).name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...