#c #linux
#c #linux
Вопрос:
Мои указатели имеют тип ‘ab’, который является экземпляром структуры с элементами: state, deadline и т.д.
Ниже показан мой текущий код:
ab **currProc; // double pointer
ab **const runnProc = amp;(*currProc);
Когда я позже обновляю значение ** currProc , изменяется даже значение ** runnProc; чего я не требую.
Пожалуйста, обратите внимание: я не могу изменить объявление с ab **const runnProc = amp;(*currProc);
на const ab** runnProc = amp;(*currProc);
либо, потому что я изменяю элемент, например: (*runnProc)->state
позже.
Комментарии:
1. Чего вы пытаетесь достичь? currProc и runnProc указывают на один и тот же объект, поэтому неизбежно, что любые изменения в этом объекте будут видны через оба указателя.
2. Позже я хочу иметь возможность изменять то, на что указывает currProc, без изменения runnProc @SvenNilsson
3. Вам действительно нужен двойной указатель для этого? Также обратите внимание, что разыменование указателя, который ни на что не указывает, является незаконным. В вашем примере currProc нигде не указывает, но вы используете (* currProc) .
4. Нет, currProc указывает на указатель, который указывает на экземпляр ab .
5. @Junaid Конечно, важно, на что указывает указатель! Если у вас есть указатель, и вам все равно, на что он указывает, это все равно, что иметь адрес дома, но не заботиться о том, чей это дом. И затем вы говорите всем своим друзьям «эй, идите сюда на вечеринку» и даете им адрес какого-то случайного незнакомца, потому что вам было все равно, чей это адрес. Если currProc указывает на переменную v1, а runnProc также указывает на переменную v1, то очевидно, что *currProc и *runnProc одинаковы, и единственный способ сделать их разными — это заставить их указывать на разные переменные.
Ответ №1:
Это …
ab **const runnProc = amp;(*currProc);
… выражает, что указатель runnProc
не может быть изменен, но ничего не говорит о ab *
том, можно ли изменить, указывает ли он, если таковой имеется, или ab
указывает, если таковой имеется, с помощью выражений, включающих runnProc
или иным образом. Более того, инициализация делает (неизменяемое) значение runnProc
указателем на тот же объект, на который *currProc
указывает, так что да, из этого следует, что если вы не изменяете указатель currProc
или *currProc
между, то
Когда я позже обновляю значение **currProc , даже значение **runnProc изменяется
Два выражения ссылаются на один и тот же объект.
Даже если вы вместо этого объявили runnProc
как
const ab **runProc = /* ... */;
, это не означает, что значение **runProc
после этого всегда будет одинаковым. Это просто означает, что объект, на который ссылается выражение **runProc
, не может быть изменен с помощью этого выражения. Если указанный объект сам по себе не объявлен const
, то его всегда можно изменить с помощью другого, const
неквалифицированного значения lvalue, ссылающегося на него.
Если, как вы говорите, вы не можете изменить способ инициализации runnProc
, и вы не можете избежать изменения **currProc
, по крайней мере, без предварительного изменения *currProc
, то это конец истории. Ваш код должен быть готов к тому, что **runnProc
изменится. Никакая форма const
-qualification типа runnProc
‘s не влияет на это вообще.
Обновить
Возможно, вы хотите создать копию значения **currProc
for runnProc
, на которое косвенно указывает. Наивный способ сделать это может быть,
ab runnAb = **currProc; // this is where the copy is made
ab *runnAb_p = amp;runnAb; // you need this because you want a double pointer
ab **runnProc = amp;runnAb_p; // there doesn't seem to be any need for const-ness here
Этого может быть достаточно для ваших нужд, но невозможно сказать наверняка, не зная больше о типе ab
и о том, как вы его используете, а также о том, как вы используете *currProc
. В частности, это создает runnAb
как неглубокую копию начального **currProc
, поэтому тогда все еще может быть наложение псевдонимов между объектами, доступными через члены **currProc
, и объектами, доступными через члены **runnProc
. Кроме того, неясно, что вы ожидаете, когда currProc
или *currProc
будет изменен, или это действительно актуальная проблема.
Не существует универсального подхода к созданию копий объектов.
Комментарии:
1. Есть ли способ, которым я могу указать переменную на то, на что в настоящее время ссылается
**currProc
только. И позже не позволяйте изменению**curProc
вообще влиять на переменную. @Джон Боллинджер2. Потому что я согласен с изменением моей инициализации runnProc.
3. Если я понимаю, что вы пытаетесь спросить, @Junaid, тогда ответ «нет». Назначение указателя для указания на объект не может повлиять на то, является ли этот объект изменяемым. Однако вы могли бы создать независимую копию объекта, на который
*currProc
изначально указывает, иrunnProc
указать указатель на него . Но для этого потребуется нечто большее, чем просто изменение способа инициализацииrunnProc
.4. Я хочу попробовать этот независимый подход к копированию, как именно я это сделаю? Потому что я понимаю, что моя текущая реализация runnProc должна измениться. @Джон Боллинджер
5. Очень хорошо, @Junaid, я добавил несколько комментариев по этому поводу. Но мне здесь слишком многое неизвестно, чтобы я мог с уверенностью дать вам подробный рецепт. Вам нужно выполнить часть работы самостоятельно, основываясь на деталях контекста, в котором вы это используете.
Ответ №2:
Это то, что вы ищете?
ab* otherprocPtr = (ab*)malloc(sizeof(ab));
ab* currprocPtr = (ab*)malloc(sizeof(ab));
ab* runnprocPtr = currprocPtr; // now pointing to same object
ab** currProc = amp;currprocPtr;
ab** runnProc = amp;runnprocPtr;
*currProc = otherprocPtr; // update one so it points to the other
Комментарии:
1. Хорошо, прежде всего, ‘новое’ выражение не существует для C, верно
2. Хорошо, я обновил код, но вы, наверное, все равно понимаете, что я имею в виду 🙂
3. Позвольте мне попробовать этот подход и посмотреть
4. Я использовал подход, изложенный в ответе выше этого ответа, в любом случае спасибо 🙂