исправление константного указателя на переменную - PullRequest
2 голосов
/ 04 апреля 2011

Я не могу понять, как сказать C, что я хочу указатель, который не будет двигаться.Он всегда будет указывать на один и тот же массив.Тем не менее, члены массива не являются постоянными, но сам массив является глобальным, и поэтому он находится в фиксированной позиции.

Итак, когда я кодирую это:

#include <stdio.h>

int v[2]={0, 1};
const int *cpv=v;

int main(void)
{
    v[1]=2;     printf("%d\n", v[1]);
    *(cpv+1)=3; printf("%d\n", v[1]);
    cpv[1]=4;   printf("%d\n", v[1]);
}

И получаемэто ошибки:

constp.c: In function ‘main’:
constp.c:9: error: assignment of read-only location '*(cpv + 4u)'
constp.c:10: error: assignment of read-only location '*(cpv + 4u)'

Я понимаю, что компилятор считает, что мне нужно const int v[2] для использования с const int *iv.Как получить постоянный указатель для выполнения работы?

Если вы видите сообщение об ошибке, я даже не перемещаю указатель (например, pv++).Я просто разыменовываю, что это сместило некоторые байты.

Если я сделаю это:

int *pv=cpv;
*(pv+1)=5;  printf("%d\n", v[1]);
printf("%p == %p !?\n", cpv, pv);

Я получу это предупреждение, но оно работает:

constp.c:9: warning: assignment discards qualifiers from pointer target type
pointer# ./constp 
5
0x601020 == 0x601020 !?

Спасибо,Беко.

Ответы [ 5 ]

5 голосов
/ 04 апреля 2011

Переместить квалификатор const:

int *const cpv=v;

Объяснение: в правилах объявления C это читается справа налево, начиная с идентификатора: "cpv - это постоянный указатель на int". Ваша версия будет выглядеть так: «cpv - это указатель на int константу».

Обратите внимание, что cpv+1 по-прежнему даст вам указатель на int после *cpv; создание указателя const предотвращает только ++, --, += и -= на нем.

2 голосов
/ 04 апреля 2011

Указатели типа «читать в обратном направлении»:

const int * p;

В этом случае «p» является (переменным) «указателем» на «const int».Буквально, прочитайте это в обратном порядке, с '*', означающим «указатель»: «Pointer ... to int const».

Любопытно, что следующееэто то же самое:

int const * p;  // same thing

Чтение в обратном направлении, это говорит, "указатель ... на const int" (то же самое).

Итак, если вы хотите, чтобы ваш указатель был «постоянным» (не переменным), вам нужно выполнить обратное чтение и сделать именно это:

int * const p;  // p cannot change

Теперь «p» является константойуказатель на непостоянное целое число.Не для того, чтобы читать, но читая в обратном направлении, это "указатель констант ... на int".

Используя приведенный выше пример "то же самое", мы можем теперь иметьпостоянный указатель на постоянное целое число (следующие одинаковые):

const int * const p;
int const * const p;

Вы должны прочитать их в обратном направлении, и они оба говорят одно и то же, "константа-указатель ...к константе int ".

2 голосов
/ 04 апреля 2011

Вы используете указатель на const, а не указатель на const.

const int * cpv = v;

должно превращаться в:

int * const cpv = v;

1 голос
/ 04 апреля 2011
int * const cpv=v;

Сказав это, зачем вообще нужен указатель?Компилятор сможет работать лучше, если вы обращаетесь к переменной v напрямую.Если вы используете указатель, сгенерированный код должен читать указатель из памяти каждый раз, когда вы обращаетесь к массиву.

1 голос
/ 04 апреля 2011
#include <stdio.h>

int v[2]={0, 1};
//const int       *      cpv=v; // cpv is a pointer to int const
//      int const *      cpv=v; // cpv is a pointer to const int == same as above ==
        int       *const cpv=v; // cpv is a constant pointer to int
//      int const *const cpv=v; // cpv is a constant pointer to const int
//const int       *const cpv=v; // cpv is a constant pointer to int const == same as above ==
//const int const *const cpv=v; // == same as above ==

int main(void)
{
    v[1]=2;     printf("%d\n", v[1]);
    *(cpv+1)=3; printf("%d\n", v[1]);
    cpv[1]=4;   printf("%d\n", v[1]);
}
...