#c #pointers
Вопрос:
В приведенном ниже примере указатель p
-это указатель на переменную a
.
Я увеличил значение p
на 1, что увеличивает значение на 4, потому что оно равно int. Но когда я пытаюсь напечатать значение *p
, отображается какое-то другое значение.
Я также прикрепил выходные данные вместе с программой.
Может кто-нибудь объяснить, почему отображается это значение *p
?
// POINTERS
#include<stdio.h>
int main(){
int a = 3;
int *p = amp;a;
printf("Value of p %d n",p);
printf("Value of *p %d n",*p);
p = p 1;
printf("After changing : value of p %d n",p);
printf("After changing : value of *p %d n",*p);
return 0;
}
Выход:
Ссылка [1]: https://i.stack.imgur.com/sTYlq.jpg
Комментарии:
1. Какой ценности вы ожидали? Какова цель этого последнего
printf
? В коде нет комментариев.2. Вы действительно увеличили значение p на 1. Это изменяет адрес, на который указывает указатель. В этом случае этот адрес содержит значение мусора, поэтому поведение не определено, когда вы пытаетесь разыменовать его.
3. Если вы хотите получить
4
в качестве вывода, вам придется перейтиp = p 1;
на*p = *p 1;
4. Эта программа имеет неопределенное поведение и может выдавать любые выходные данные вообще или вообще ничего. Вот один из возможных выходов .
5. Ваш вывод-обычный текст. Пожалуйста, просто скопируйте и вставьте его в виде отформатированного текста в свой вопрос (вы можете использовать кнопку редактирования под своим вопросом) вместо показа картинок.
Ответ №1:
Может кто-нибудь объяснить, почему отображается это значение *p?
Нет, никто не может объяснить, почему последний отпечаток *p
дает то значение, которое вы видите.
И завтра он может напечатать другое значение… или не напечатать вообще… или ваша программа может выйти из строя… или может произойти что-то другое…
Это называется неопределенным поведением.
Вы пытаетесь прочитать ячейку памяти (т. е. исходную p
1), как если int
бы в этой ячейке находился объект. Но это не так… стандарт C не определяет, что должно произойти, когда вы это сделаете. Так что может случиться все, что угодно.
Далее обратите внимание, что на самом деле у вас уже есть неопределенное поведение здесь:
printf("Value of p %d n",p);
^^
Wrong for pointers and therefore undefined behavior
Чтобы напечатать указатель, вы должны использовать %p
и привести указатель к пустому указателю. Нравится:
printf("Value of p %p n", (void*)p);
^^ ^^^^^^^
Specifier cast to void-pointer
for void-pointer
Итак, легальная версия вашей программы:
int a = 3;
int *p = amp;a;
printf("Value of p %p n", (void*)p);
printf("Value of *p %d n",*p);
p = p 1;
printf("After changing : value of p %p n", (void*)p);
// printf("After changing : value of *p %d n",*p); <-- Illegal so commented out
Комментарии:
1. Хорошо, значит, поведение не определено!! Понял, спасибо 👍 👍
Ответ №2:
Вы получаете доступ к памяти, к которой у вас (обязательно) нет доступа.
Представьте a
, что (длиной 4 байта) находится здесь
- - - - - - - - - - - -
| | | |a|a|a|a| | | | | |
- - - - - - - - - - - -
^ ^ ^ ^ ^ ^ ^ ^ <== memory you do not have access to
------ | <== p points here
------ <== p 1 points here and the pointer is valid
Доступ к памяти, к которой у вас нет доступа, является неопределенным поведением.