Может кто-нибудь, пожалуйста, объяснит результат этой программы?

#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
 

Доступ к памяти, к которой у вас нет доступа, является неопределенным поведением.