Разница между указателем [0] и * указателем в C? - PullRequest
0 голосов
/ 23 января 2019

Итак, у меня есть следующий массив fib_sequence в C, переданный в функцию как *fib_sequence[].

Моя функция отключается при доступе к элементу:

*fib_sequence[i]

Однако это работает, когда я делаю:

fib_sequence[0][i]

Я схожу с ума или они не эквивалентны?

Для справки здесь приводится вся функция, она не выполнялась при назначении только для индекса 1 .

Функция Segfault

void fib(int *fib_sequence[], int count) {
    *fib_sequence = malloc(sizeof(int[count]));

    for (int i = 0; i < count; i++) {
        if (i == 0) {
            *fib_sequence[i] = 0;

        } else if (i == 1) {
            *fib_sequence[i] = 1;

        } else if (i >= 2) {
            *fib_sequence[i] = *fib_sequence[i-2] + *fib_sequence[i-1];
        }
    }
}

Рабочая функция

void fib(int *fib_sequence[], int count) {
    *fib_sequence = malloc(sizeof(int[count]));

    for (int i = 0; i < count; i++) {
        if (i == 0) {
            fib_sequence[0][i] = 0;

        } else if (i == 1) {
            fib_sequence[0][i] = 1;

        } else if (i >= 2) {
            fib_sequence[0][i] = fib_sequence[0][i-2] + fib_sequence[0][i-1];
        }
    }
}

Ответы [ 4 ]

0 голосов
/ 23 января 2019

Обратите внимание, что int *fib[] анализируется как int* (fib)[]; то есть неограниченный массив int*. Вы, вероятно, имели в виду int (*fib)[]: указатель на неограниченный массив целых чисел. Как только вы сделаете это изменение, ваш первый пример больше не будет компилировать (как и должно быть), но (*fib_sequence)[i] и fib_sequence[0][i] оба будут работать (также как и должны).

Однако *fib_sequence = malloc(sizeof(int[count])) теперь является ошибкой, потому что вы не можете присвоить значение массива. Это означает, что вам придется переместить malloc за пределы функции или отказаться от синтаксиса int (*fib)[] и использовать вместо него int** fib.

0 голосов
/ 23 января 2019

Вы хотите знать, что унарные * и [] имеют различный "приоритет", и ваше выражение

*foo[1]

фактически анализируется как

*(foo[1])

Вам необходимо заключить в скобки свое «предпочтение», чтобы оно функционировало правильно:

(*foo)[1]

Примечание: в некоторых случаях *p не эквивалентно p[0], хотя оно всегда эквивалентно *(p + 0) (обратите внимание на арифметику указателя здесь).

Следовательно, вы можете обнаружить, что p[0] отказывается от компиляции, когда p является указателем на функцию, потому что он не может участвовать в арифметике указателей. Однако для указателей данных значения *p и p[0] на самом деле не имеют никакого значения.

0 голосов
/ 23 января 2019

*pointer и pointer[0] точно такие же в C. Но это означает, что *fib_sequence[i] - это то же самое, что и fib_sequence[i][0], что НЕ совпадает с fib_sequence[0][i] (если только i не равно 0 ). Суффиксные операторы в C имеют более высокий приоритет, чем префиксные операторы.

0 голосов
/ 23 января 2019

Они не эквивалентны, потому что постфиксные операторы имеют более высокий приоритет, чем унарные.Это означает, что *fib_sequence[i] на самом деле означает *(fib_sequence[i]).Тогда под эквивалентностью *(E) и (E)[0], которую вы правильно понимаете, это выражение означает (fib_sequence[i])[0], из которого мы можем отбросить ненужные скобки, чтобы получить fib_sequence[i][0].

Запомните постфикс в сравнении с унарным / префиксом: *E, ++E, &E и другие являются унарными операторами.E(...), E[], E->memb, E.memb - это постфиксы.

Все унарные и постфиксы можно объединять в одно целое.Когда postfix комбинируется с postfix, становится ясно: они идут в одном направлении, от корневого выражения слева направо: E[i]->foo.memb(arg)[blah].Приоритет все тот же, и ассоциативность, очевидно, может быть только слева направо.

Когда унарные объединены, то же самое в противоположном направлении: sizeof (T) &*++E.Приоритет все тот же, а ассоциативность справа налево.Все они выше, чем различные бинарные операторы.

Если мы соединим эти два, нам вряд ли придется думать:

sizeof (T) &*++E[i]->foo.memb(arg)[blah]

Как только мы просканируем унарные операторы, чтобы найти E, ситуация с приоритетом будет просто такой:

sizeof (T) &*++ ( E[i]->foo.memb(arg)[blah] )
                ^---------------------------^

все постфиксовые крафт имеют более высокий приоритет, чем унарный.

Постфиксы имеют наивысший приоритет, за ними следуют унарные символы, затем все остальное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...