4

Hello all I have a very basic question while learning to code in c++.

I am reading about the difference between pass by reference and pass by value. I wrote a simplistic code to test it but it does something I didn't expect.

    #include <iostream>
    using namespace std;

    void MyIncr (float *x);
    int main() {
        float score = 10.0;
        cout << "Orignal Value = " << score << endl;
        MyIncr(&score);
        cout << "New Value = " << score << endl;
     }

     void MyIncr (float *x) {
        *++x;
     }

How come I get 10 for both couts? However if I change the function to be something like:

     void MyIncr (float *x) {
        *x += 1;
     }

I get 10 for the old value and 11 for the new, which is what I would have expected in the previous case as well.

vkaushal
  • 41
  • 3
  • 2
    That isn't "pass by reference", it's "pass a pointer by value". Pass by reference would be `void MyIncr (float & x);` –  Jul 10 '18 at 16:39
  • 1
    Also `*++x;` does not increment the pointed to value - it first increases the pointer by 1 and then dereferences it (invoking *undefined behavior*) – UnholySheep Jul 10 '18 at 16:41
  • is *x++ also undefined behaviour? – SynAck Jul 10 '18 at 16:50
  • @Ali yes; you're incrementing the pointer, and then dereferencing it. – frslm Jul 10 '18 at 16:51
  • okay,I got the answer here:[C - pointer behavior with pre and post increment](https://stackoverflow.com/questions/27012198/c-pointer-behavior-with-pre-and-post-increment) and [Difference between ++*argv, *argv++, *(argv++) and *(++argv)](https://stackoverflow.com/questions/26902462/difference-between-argv-argv-argv-and-argv/26902610#26902610) – SynAck Jul 10 '18 at 16:59
  • @vkaushal Do you mean `++(*x)` and `(*x)++`? – Ruks Jul 10 '18 at 17:04
  • @Ali sorry for the confusion - in this particular case `*x++` is legal, but won't actually increment whatever `x` is pointing to. And if you try to dereference `x` afterwards, you'll get undefined behaviour. – frslm Jul 10 '18 at 17:08
  • Yes @Ruks it should have been how you and many others have put it. However I didn't realize `x++` could be different from `x+=1` in certain situations. Also I think I need to change the online C++ tutorial I am taking :). – vkaushal Jul 10 '18 at 17:26

3 Answers3

6
 void MyIncr (float *x) {
    *++x;
 }

Is undefined behavior in this context. You are incrementing the pointer first, then dereferencing it. When the pointer is incremented, it no longer points to a valid float object. Hence, dereferencing it is undefined behavior.

On the calling side, nothing happens to the pointer or the value of object the pointer points to. To increment the value of the object that the pointer points to, use ++(*x).

 void MyIncr (float *x) {
    ++(*x);
 }

It will be better to pass the object by reference. There will be less confusion.

 void MyIncr (float& x) {
    ++x;
 }
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

The issue is here:

*++x;

If you check out C++ Operator Precedence you will see that the Prefix ++ operator is given equal precedence as the dereferencing * operator and are therefore evaluated right-to-left. This means that the above line of code first increments the pointer (because ++ is the right most operator), then tries to dereference it. If you wish to keep the ++ operator you can switch the order of the operators.

++*x;

In my opinion it would be more readable to use brackets however.

++(*x);
Jacob Boertjes
  • 963
  • 5
  • 20
1

Adding to R sahu's answer.This happens due to precedence of operators and their associavity.

void MyIncr (float *x) {
    *++x;
 }

Pre-increment(++) and dereference or indirection(*) operator have the same precedence and are right to left associative.Hence whichever operator is on the right it will be executed first.Therefore in your case, the pointer to x will be incremented first and then dereferenced.So to get 11 do this:

void MyIncr (float *x) {
    ++*x;//even without the parenthesis this will work
 }

Again pass by reference is the best way to go about it.Call the function like this MyIncr(x) and the function should look like this

void MyIncr (float& x) {
    ++x;
 }
SynAck
  • 427
  • 5
  • 19