Инкремент указателя и приоритет объединения в цепочку в C#

Я видел эту часть кода C# в одной из статей MSDN:

using System; class Test
{
   public static unsafe void Main() 
   {
      int* fib = stackalloc int[100];
      int* p = fib;
      *p++ = *p++ = 1;
      for (int i=2; i<100; ++i, ++p)
         *p = p[-1] + p[-2];
      for (int i=0; i<10; ++i)
         Console.WriteLine (fib[i]);
   }
}

Я довольно плохо знаком с указателями. Я понимаю большую часть этого кода, но было бы замечательно, если кто-то может помочь мне понять эту строку в вышеупомянутом коде более подробно:

*p++ = *p++ = 1 
9
задан Hari Menon 7 June 2012 в 16:21
поделиться

6 ответов

Это просто ленивый (другие бы сказали идиоматический) способ записи

*p++ = 1;
*p++ = *p++;

или, возможно, лучше понять:

*p=1;
p++;
*p=1;
p++;
8
ответ дан 4 December 2019 в 12:59
поделиться

В приведенном выше коде вы генерируете 100 чисел в ряду Фибоначчи.

в строке * p ++ = * p ++ = 1, вы инициализируете первые 2 числа равными 1. т.е. заполнение числа 1 в местах, указанных указателем.

Изначально указатель указывает на 0. Когда вы выполняете * p ++, это означает, что указатель должен быть перемещен вперед на одно место от того места, на которое он указывает.

Таким образом, в этом случае значение в позиции 1 присваивается значению в позиции 2, которому присваивается значение «1». т.е. * p ++ = * p ++ = 1

1
ответ дан 4 December 2019 в 12:59
поделиться

Это означает, что в 0 и 1 позициях выделенной памяти значения установлены в 1.

Для более ясного понимания: p* указывает на некоторый адрес памяти, пусть это будет start, прямо на другой адрес памяти, который равен start + sizeof(int)*100, пусть это будет end.

В этом примере в 1 были установлены элементы по адресу start и start + sizeof(int). Пост-инкремент (*p++) означает, что сначала используется p*, а затем он увеличивается на значение sizeof(int), второй *p++ означает, что теперь мы используем *p + sizeof(int), а затем он увеличивается еще раз и мы имеем *p + sizeof(int)*2.

2
ответ дан 4 December 2019 в 12:59
поделиться

Вам нужно разбить вещи на части:

* p ++

Это делает две вещи: разыменование p и пост-инкремент. Т.е. показать, что находится по адресу p сейчас (или присвоить ему) и после увеличить его (до следующей ячейки памяти).

Таким образом, два из них позволяют назначать начальную и вторую ячейки памяти (оставляя p со ссылкой на третью).

C # позволяет назначать цепочки: a = b = 2 присваивает 2 обоим a и b .

NB не пробуйте это в C или C ++, изменяя одно и то же ( p ) более одного раза в одном выражении undefined. Но C # это определяет.

2
ответ дан 4 December 2019 в 12:59
поделиться

В C# *p++ = *p++ = 1; эквивалентно:

 *p++ = 1;
 *p++ = 1;

Таким образом, первые 2 элемента массива (на которые первоначально указывал p) инициализируются 1, а p остается указывать на третий элемент (элемент 2, используя нулевую нотацию).

В качестве отступления отметим, что аналогичное выражение в C/C++ имело бы неопределенное поведение, поскольку указатель p модифицируется более одного раза без промежуточной "точки следования". Однако в C# выражение оценивается вполне определенным образом.

2
ответ дан 4 December 2019 в 12:59
поделиться

Первые три числа fib равны 0, 1, 1, и именно это делает код. (Ноль здесь пропущен)

Более понятно было бы написать:

*p++=1; // second fib
*p++=1; // third fib. 
1
ответ дан 4 December 2019 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: