Typedef указатель const weirdness

рассмотрите следующий код:

typedef struct Person* PersonRef;
struct Person {
  int age;
};

const PersonRef person = NULL;

void changePerson(PersonRef newPerson) {
  person = newPerson;
}

По какой-то причине компилятор комментирует значение, доступное только для чтения, которое нельзя назначить. Но ключевое слово const не должно указывать указатель const. Любые идеи?

Ответы

Ответ 1

Обратите внимание, что

typedef int* intptr;
const intptr x;

- это не то же самое, что:

const int* x;

intptr является указателем на int. const intptr является постоянным указателем на int, а не указателем на константу int.

поэтому, после указателя typedef, я больше не могу сделать его const содержимым?

Есть некоторые уродливые способы, такие как gcc typeof macro:

typedef int* intptr;
intptr dummy;
const typeof(*dummy) *x;

но, как видите, это бессмысленно, если вы знаете тип за intptr.

Ответ 2

const PersonRef person = NULL;

есть

struct Person*const person= NULL;

чтобы вы указали указатель, а не объект.

Ответ 3

Хотя проблема уже решена вышеприведенными ответами, я пропустил причину, по которой...

Итак, возможно, как правило:

  • const всегда ссылается на токен предшественника.
  • В случае, если таковой нет, он вместо этого "конструирует" вместо этого токен преемника.

Это правило действительно может помочь вам объявить указатель на указатели const или что-то в равной степени аккуратное.

В любом случае, имея в виду это, должно быть ясно, почему

struct Person *const person = NULL;

объявляет указатель const к изменяемой структуре.

Подумайте об этом, ваши typedef "группы" struct Person с токеном указателя *. Итак, для написания

const PersonRef person = NULL;

ваш компилятор видит что-то вроде этого (псевдокод):

const [struct Person *]person = NULL;

Как только ничего не осталось const, он объявляет токен правой константе struct Person *.

Ну, я думаю, именно по этой причине мне не нравятся скрытые указатели typedefs, в то время как мне нравятся typedefs как таковые. Как насчет написания

typedef struct Person { ... } Person;
const Person *person; /*< const person */
Person *const pointer; /*< const pointer to mutable person */

и должно быть совершенно понятно компиляторам и людям, что вы делаете.

Ответ 4

Никогда не скрывайте указатели позади typedefs, это действительно очень плохая практика и создаст ошибки.

Одна из таких печально известных ошибок заключается в том, что тип typedef: ed pointer, объявленный как const, будет рассматриваться как "постоянный указатель на непостоянные данные", а не "постоянный указатель на постоянные данные", что и есть один интуитивно ожидает. Это то, что происходит в вашей программе.


Решение:

typedef struct
{
  int age;
} Person;

const Person* person = NULL; // non-constant pointer to constant Person

Ответ 5

вы получаете и ошибки

error: assignment of read-only variable ‘person’

on statement

person = newPerson;

потому что вы объявили человека как const, поэтому его значение только для чтения.... Значение const не может быть изменено

если вы собираетесь изменить эту жизнеспособность, то почему вы kepping it const?

удалить ключевое слово const, ваш код будет работать нормально