необъяснимое изменение значения при использовании указателя типов - PullRequest
0 голосов
/ 31 декабря 2018
 #include <stdio.h>
 int main() { 

   int num=1;
   char *b;
   b=(char*)&num;
   *(++b)=2;
   printf("%d\n",num);

   return 0; 
}

Когда я скомпилировал этот код, я встретил «513» в качестве вывода.Когда я использую строку комментария для этой строки:

*(++b)=2;

Вывод преобразуется в «1».

Почему я столкнулся с «513» в качестве вывода?

Почему выходные данные изменились при использовании строки комментария, которую я подразумевал?

Ответы [ 4 ]

0 голосов
/ 31 декабря 2018

Когда я скомпилировал этот код, я обнаружил "513" в качестве вывода.

Вы получаете этот вывод из-за этого оператора:

*(++b)=2;

Первоначальноb указывает на num.Оператор *(++b)=2 сначала будет увеличивать указатель b и указывать на следующий байт, а затем разыменовывать его и присваивать 2.
Если на вашей платформе int равен 32 бит, то:

initially
num = 1

00000000 00000000 00000000 00000001


num after this statement
*(++b)=2;

00000000 00000000 00000010 00000001

which is the binary representation of `513`.

Когда я использую строку комментария для этой строки: *(++b)=2; Выходные данные преобразуются в «1».

Конечно, вы инициализировали num с помощью 1 и чтоиначе вы ожидаете при печати num без каких-либо изменений.

0 голосов
/ 31 декабря 2018

Это

int num=1;

, представленное в 32 bit системе, как показано ниже

     0x103      0x102       0x101       0x100  (let's assume base address of num 0x100)
  -----------------------------------------------
 | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 |
  -----------------------------------------------
                                                num
MSB                                          <--LSB

А здесь

char *b; /* char pointer i.e at a time points to 1 byte */
b=(char*)&num; /* b points to &num i.e 0x100 in above diagram */

выглядит как

    0x103      0x102       0x101       0x100  
  -----------------------------------------------
 | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 |
  -----------------------------------------------
                                                num
                                                 b <-- b points here 

Теперь, когда выполняется

*(++b)=2;

, сначала происходит ++b, что означает, что указатель на символ b увеличивается на один байт, т. Е. Он указывает на местоположение 0x101, а затем содержимое только * 1020.* местоположение, назначенное 2.Это выглядит как

     0x103      0x102       0x101       0x100  
  -----------------------------------------------
 | 0000 0000 | 0000 0000 | 0000 0010 | 0000 0001 |
  -----------------------------------------------
                                     |          num
                                     b <-- b points to 0x101  

Теперь, когда вы печатаете num, он печатает 512 + 1, что составляет 513.Надеюсь, это очистит ваши сомнения.

0 голосов
/ 31 декабря 2018

Предполагая, что int является 32-битным с порядком байтов с прямым порядком байтов в вашей системе, представление num равно 0x00000001 и выглядит в памяти следующим образом:

-----------------
| 1 | 0 | 0 | 0 |
-----------------

Затем вы указываетеb до num:

  b
  |
  v
-----------------
| 1 | 0 | 0 | 0 |
-----------------

Затем вы делаете *(++b)=2;, оно увеличивает b, разыменовывает увеличенный указатель и записывает 2 в это место.Итак, теперь у вас есть.

      b
      |
      v
-----------------
| 1 | 2 | 0 | 0 |
-----------------

Итак, теперь представление num равно 0x00000201`, что составляет 513 в десятичном виде.

0 голосов
/ 31 декабря 2018

Похоже, что на вашей машине символы имеют байтовый размер.Вот почему вы видите это совершенно нормальное поведение.

Ваша переменная num выглядит в памяти следующим образом.

0x00000001

Вы берете его адрес, рассматриваете его как символ* затем установите второй символ в 2, так что теперь ваше число становится равным.

0x00000201

Когда вы преобразуете это обратно в десятичное, оно правильно выдает 513.

...