Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer increment operator errors

Ok so this one has me really confused. I'm working on a HW problem, and discovered something that was really weird to me. here is the function and call in question

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;

}

So to make a long story short, I get a popup (in windows) that says there was a problem and has to close.

When I try replacing *ptr++; with *ptr+=1;

The program runs. This got me interested so I used -S in gcc With the *ptr++ version I get this instruction:

addl    $4, -20(%ebp)

with *p+=1 I get

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

Which to me looks like a very similar operation, so assuming I'm reading this correctly,

case 1

Increment -20(%ebp) by 4 (assuming $4 means that)

case 2

we store what is in ebp to eax,

(not sure what () do), but do it again?

then take and load the address from eax offset by 4 into edx,

now copy ebp back into eax again,

now copy edx into eax,

I mean it looks like they're doing the same thing, but for some reason *ptr++ != *ptr+=1

Why? What am I missing from what I see?

EDIT: THANKS Everyone now I feel special, I can't believe I didn't realize that!

like image 623
onaclov2000 Avatar asked Dec 22 '22 21:12

onaclov2000


2 Answers

This is actually an issue with the operator precedence. The postfix increment operator gets applied before the pointer is dereferenced, meaning that you increment the value of the pointer (the memory it points to) and then attempt to dereference it. This is invoking undefined behaviour since it points to a single int.

In the latter case, the += is applied after the dereference occurs, so you get the value stored at the pointer's memory, then you add to it. You need to make sure the dereference occurs first if you want to use postfix increment, which you can do by using:

(*ptr)++;

instead of what you currently have.

like image 70
eldarerathis Avatar answered Jan 06 '23 01:01

eldarerathis


This

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

should be

 (*ptr)++;

Operator precedence matters here - *ptr++ works this way: *(ptr++) - the same way as

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

copies a null-terminated string.

like image 41
sharptooth Avatar answered Jan 06 '23 00:01

sharptooth