Приращение указателя и приоритет цепочки в C # - PullRequest
9 голосов
/ 11 июля 2010

Я видел этот фрагмент кода 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 

Ответы [ 6 ]

8 голосов
/ 11 июля 2010

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

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

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

*p=1;
p++;
*p=1;
p++;
2 голосов
/ 11 июля 2010

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

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

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

2 голосов
/ 11 июля 2010

Вы должны разбить вещи:

*p++

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

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

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

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

2 голосов
/ 11 июля 2010

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

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

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

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

1 голос
/ 11 июля 2010

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

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

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

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

1 голос
/ 11 июля 2010

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

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

*p++=1; // second fib
*p++=1; // third fib. 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...