1

I have written a program that flips the elements of an array that are next to each other. for example

1, 2, 1, 2 becomes 2, 1, 2, 1

The code I wrote is:

#include <iostream>


template <class T>
void swap(T& a, T& b){
    T temp = a;
    a = b;
    b = temp;
}
template <class T>
void oReverse(T* p, int size){
    for(T* e = p + size; p < e; p+=1){
        swap(*p, *p++);
    }

}
int main(){
    int arr[] = {1,2,1,2,1,2};
    oReverse(arr, 6);
    for(int i = 0; i < 6; i++){
        std::cout << arr[i] << " ";
    }
    return 0;
}

The oReverse() function takes care of the pointer magic. The thing i couldn't understand is: Why does swap(*p, *p++) increment p by one. At first I wrote p+=2 in the for loop, but it didn't work well, but it does with p++. I thought the program would swap p and p++ then increment p by 2 then swap p and p++ again and again.

I hope i explained the problem clearly enough.

TommyGun
  • 25
  • 4
  • 1
    Is this supposed to compile? I ask because.. well.. it doesn't. – WhozCraig Nov 02 '20 at 13:46
  • `p++` increments p by one. – Eljay Nov 02 '20 at 13:46
  • `*p++` increments `p` (at some point before the next expression) and produces the original value of `*p`. Also, the evaluation order of arguments is unspecified and your code has undefined behaviour. (Don't try to be clever and do several things in one line.) – molbdnilo Nov 02 '20 at 13:47
  • oups i left the ( std::cout << a << b << std::endl;) i'll edit it out sorry. – TommyGun Nov 02 '20 at 13:48
  • That's not the reason this fails to compile. The unfinished `reverse` function opening is nesting everything past it. Frankly I don't see the need for that entire line. – WhozCraig Nov 02 '20 at 13:52
  • I forgot that too... I think the program should be able to compile now. – TommyGun Nov 02 '20 at 13:58
  • `Do pointer arithmetic expressions count as instructions?` No. Pointer arithmetic expressions are constructs in the C++ language. Instructions are constructs of an assembly language and machine code. – eerorika Nov 02 '20 at 14:15

1 Answers1

8

Firstly, *p++ increments p after the value is fetched. So instead of

swap(*p, *p++);

you would like to do this:

swap(*p, *++p);

But this will not work either. The standard does not define in which order the arguments to a function should be evaluated. So instead of

swap(*p, *++p);

write

swap(*p, *(p+1));
p++;

and you'll be safe. Their behavior are not equivalent, because the evaluation order is unspecified. But their expected behavior are equivalent.

With "expected behavior", I mean the behavior someone who does not know that the evaluations order is not defined by the standard typically would expect.

EDIT:

The evaluation order was unspecified before C++17, but from C++17 it is specified from left to right. But still, don't do things like that. "Clever" constructs have a tendency to cause problems.

klutt
  • 25,535
  • 14
  • 43
  • 72