Не могу получить результат указателей - PullRequest
0 голосов
/ 24 января 2019
#include<stdio.h>
void main()
{
    int v=10;
    char *p=&v;
    int i;
    for(i=0;i<10;i++,p++)
    {
        ++(*p);
        printf("%d",v);
    }
}

Вывод

11
267
65803
16843019
16843019
16843019

Я не понимаю, как получился вывод, как это, пожалуйста, объясните

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я не понимаю, как получился вывод, как это, пожалуйста, объясните

Сначала давайте внесем небольшие изменения в ваш код и напечатаем значения в шестнадцатеричном виде:

int main() {
  int v = 10;
  char *p = (char*)&v;
  int i;
  printf("%8d (0x%08x)\n", v, v);
  for(i=0; i<sizeof(i); i++, p++)
  {
    ++(*p);
    printf("%8d (0x%08x)\n", v, v);
  }

  return 0;
}

Вывод:

      10 (0x0000000a)
      11 (0x0000000b)
     267 (0x0000010b)
   65803 (0x0001010b)
16843019 (0x0101010b)

Итак, что здесь происходит, так это то, что int составляет четыре байта - следовательно, я получаю 4 значения, напечатанные циклом (плюс печать перед циклом).

Поскольку p является указателем на символ, а моя система имеет младший порядок, p сначала будет указывать на младший (младший байт) целого числа, то есть "0a", и увеличивать этот байт до "0b".

Когда p увеличивается на p++, он будет указывать на следующий байт, то есть "00", и увеличивать этот байт до "01".Итак, теперь целое число содержит «0000010b» (267 десятичное число).Этот шаг повторяется дважды, так что целое число сначала становится «0001010b» (65803 десятичное число), а затем «0101010b» (16843019 десятичное).

В памяти это выглядит так:

After initialization: 0a 00 00 00
                      ^
                      |
                      p

After loop 1:         0b 00 00 00
                         ^
                         |
                         p

After loop 2:         0b 01 00 00
                            ^
                            |
                            p

After loop 2:         0b 01 01 00
                               ^
                               |
                               p

After loop 4:         0b 01 01 01
                                  ^
                                  |
                                  p

BTWОбратите внимание, что стандарт не дает никаких гарантий относительно этого поведения.Обновление байтов внутри целого числа с использованием указателя на символ недостаточно хорошо определено стандартом.

0 голосов
/ 24 января 2019

Я могу только предположить, что ожидаемое поведение - получить переменную v, увеличенную в 10 раз с помощью указателя.

Если это правильно, у вас есть две ошибки:

  1. Тип указателя должен совпадать с указанными вами данными. Если вы указываете на переменную int, вам следует использовать указатель int *.
  2. В условии цикла for: на каждой итерации вы увеличиваете i и p (i++,p++). Когда вы увеличиваете указатель, он перемещается к следующей ячейке памяти (простыми словами, на самом деле это немного сложно). Если вы хотите работать только с переменной v, вам не следует изменять сам указатель, а только переменную, к которой он относится. Таким образом, если вы удалите p++ часть, вы получите 11, 12, 13, ... в результате.

Почему он показывает такие странные результаты сейчас? Просто потому, что на каждой итерации вы меняете указатель (таким образом, он ссылается на другую ячейку памяти). Память, на которую указывает указатель после инкремента, может содержать случайные данные, которые мы можем видеть. Однако такой подход содержит неопределенное поведение, и результаты могут отличаться. Это может даже закончиться завершением программы.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...