Ошибки оператора приращения указателя - PullRequest
4 голосов
/ 01 ноября 2010

Хорошо, так что это меня очень смущает.Я работаю над проблемой HW и обнаружил что-то действительно странное для меня.вот функция и вызов, о котором идет речь

int find_oldest_frame(int **a, int size)
{
   int min = clock();
   int **ptr;
   int *ptr2;
   int frame = 0;
   int i;
   // get address of pointer so we can modify it
   ptr = a;
   // store off original pointer location.
   ptr2 = *a;

   for (i=0; i<size; i++)
   {

      // Who is the oldest time
      if (**ptr < min)
      {
         min = **ptr;
         frame = i;
      }
      printf("Current_Pointer %d\n", *ptr);
      *ptr++; // For some reason ++ doesn't work.

   }
   // now store the oldest frame with the current system time, so it's no longer the oldest.
   *ptr = ptr2;
   *ptr += frame;
   **ptr = clock();
   *ptr = ptr2;
   // Return the array index so that we can change the right page!
   return frame;

}

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

Когда я пытаюсь заменить * ptr ++;с * ptr + = 1;

Программа запускается.Это заинтересовало меня, поэтому я использовал -S в gcc. С версией * ptr ++ я получаю эту инструкцию:

addl    $4, -20(%ebp)

с * p + = 1, я получаю

movl    -20(%ebp), %eax
movl    (%eax), %eax
leal    4(%eax), %edx
movl    -20(%ebp), %eax
movl    %edx, (%eax)

Что для меня выглядиткак очень похожая операция, поэтому при условии, что я читаю это правильно,

case 1

Увеличение -20 (% ebp) на 4 (при условии, что $ 4 означает, что)

case 2

мы сохраняем то, что находится в ebp, в eax,

(не уверен, что () делать, но делаем это снова?

, затем берем и загружаем адрес изсмещение eax на 4 в edx,

теперь скопируйте ebp обратно в eax,

теперь скопируйте edx в eax,

Я имею в виду, что они делают то же самоевещь, но по какой-то причине * ptr ++! = * ptr + = 1

Почему?Чего мне не хватает в том, что я вижу?

РЕДАКТИРОВАТЬ: СПАСИБО всем теперь я чувствую себя особенным, я не могу поверить, что я не осознавал этого!

Ответы [ 4 ]

6 голосов
/ 01 ноября 2010

На самом деле это проблема с приоритетом оператора . Оператор приращения постфикса применяется до , указатель разыменовывается, то есть вы увеличиваете значение указателя (память, на которую он указывает), а затем пытаетесь разыменовать его. Это вызывает неопределенное поведение, поскольку оно указывает на один int.

В последнем случае += применяется после разыменования происходит, поэтому вы получаете значение, хранящееся в памяти указателя, а затем добавляете его. Вы должны убедиться, что разыменование происходит первым, если вы хотите использовать постфиксный инкремент, что вы можете сделать с помощью:

(*ptr)++;

вместо того, что у вас сейчас есть.

2 голосов
/ 01 ноября 2010

Приоритет оператора не совпадает.Они соответственно эквивалентны:

*(ptr++);

И:

(*ptr) += 1;

Вы можете сделать *(ptr)++;, чтобы увеличить указанное значение и оставить сам указатель без изменений.

2 голосов
/ 01 ноября 2010

Это

*ptr++; // For some reason ++ doesn't work.

должно быть

 (*ptr)++;

Здесь важен приоритет оператора - *ptr++ работает следующим образом: *(ptr++) - так же, как

 while( ( *t++ = *s++ ) != 0 );

копирует строку с нулевым символом в конце.

1 голос
/ 01 ноября 2010

Оператор ++ имеет более высокий приоритет , чем *, что имеет более высокий приоритет, чем +=.++ связывается с ptr, а += связывается с (*ptr).

...