Цепь Маркова. Метод добавления реализации

Я немного смущен следующим утверждением в реализации:

void add(char *prefix[NPREF], char *suffix) {
    State *sp;

    sp = lookup(prefix, 1);
    //addsuffix(sp, suffix);

    printf("size of prefix %d",&prefix);
    printf("size of prefix %s", prefix + 1);
    printf("size of prefix %d \n", &prefix+1);
    for (int i = 0; i < NPREF; i++)
        printf("%s \n" , prefix[i]);


    printf("memmove \n");

    memmove(prefix, prefix + 1, (NPREF - 1) * sizeof(prefix[0]));
    prefix[NPREF - 1] = suffix;

    for (int i = 0; i < NPREF; i++)
        printf("%s \n", prefix[i]);

}

mmemove(prefix, префикс + 1, (NPREF - 1) * sizeof(prefix[0]));

Итак, префикс — это указатель типа char. В этом смысле префикс + 1 — это ссылка на следующий символ в массиве, не так ли?

Как это работает правильно? Я читал о memmove и читал об указателях, но не смог самостоятельно изучить поведение этой функции добавления.


person Роман Иванов    schedule 11.07.2016    source источник
comment
printf(размер префикса %d,&префикс); неправильно   -  person 4pie0    schedule 11.07.2016
comment
Я просто пытаюсь получить ответ. Пожалуйста, не беспокойтесь о моих функциях printf. Вопрос не об этом.   -  person Роман Иванов    schedule 11.07.2016


Ответы (2)


Итак, префикс — это указатель типа char. В этом смысле prefix + 1 является ссылкой на следующий char в массиве, не так ли?

Нет и да. prefix не является указателем на char, это массив указателей NPREF на char. Размер этого массива

assert(sizeof(prefix) == NPREF * sizeof(char*)

и да, prefix + 1 - это адрес следующего элемента после &prefix[0], потому что prefix (который является массивом) распадается на указатель на первый элемент массива. Так

memmove(prefix, prefix + 1, (NPREF - 1) * sizeof(prefix[0]));

будет mommove NPREF - 1 элементов по одному местоположению. Звучит разумно, учитывая, что такое цепь Маркова, хотя мы не видим вашей реализации. Если бы вместо этого было написано как

memmove(&prefix, &prefix + 1, sizeof(prefix)/sizeof(prefix[0]);

тогда это будет memmove всего массива.

Пример:

[0][1][2][3][4][5]...[n] /* prefix was */
[A][B][C][D][E][F]...[N]
memmove(prefix, prefix + 1, (NPREF - 1) * sizeof(prefix[0]));
[0][1][2][3][4][5]...[n] /* prefix is */
[A][A][B][C][D][E]...[M]
person 4pie0    schedule 11.07.2016

memmove переместит n-1 указателей на один шаг назад.

Рассмотрим это на секунду как memcpy, который работает с двумя разными массивами:

prefix
 V    
[ ][ ][ ][ ][ ][ ]
 ^  ^  ^  ^  ^
 \  \  \  \  \
  \  \  \  \  \
   \  \  \  \  \
    \  \  \  \  \
[ ][ ][ ][ ][ ][ ]
    ^
    prefix+1
person Shloim    schedule 11.07.2016