Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

OPERATOR PREC, L-VAL, R-VAL, DEREF

Posted on 1999-06-25
10
Medium Priority
?
330 Views
Last Modified: 2010-04-16
Hi All:
I was having problems with pointers, deref, and l-values. So I set up an excercise for myself. Below is the code that I created. IT ALL WORKS THE WAY I WANT. However, I still don't understand deref pointer, oper prec, or l-val's completely.
EX.
(x++)++; l-val missing ok (x++) is an r-val.
(from item #3 in code below)
(*first++)++; How can this work? How is this statement being parsed? Does ++ left to right and * right to left allows this stmt to be parsed?
*(first++)++; Doesn't work? l-val missing ???
Second part, if any of the examples (#3 to #6) can be arranged differently (paranthesis etc.), and still have the same output, please post, and explain.



#include <vector>
#include <typeinfo>
#include <iostream>

using namespace std;

int main (void)
{
      vector<int> v(3);
      v[0] = 5;
      v[1] = 2;
      v[2] = 7;

 int x = 1;
x++;

      vector<int>::iterator first = v.begin();
vector<int>::iterator last  = v.end();
/*
"#1 deref ptr, use val, incr ptr"
VECTOR BEFORE = 5,2,7
OUTPUT 5,2,7
VECTOR AFTER = 5,2,7
"#2 incr ptr, deref ptr, use val"
VECTOR BEFORE = 5,2,7
OUTPUT 2,7
VECTOR AFTER = 5,2,7
"#3 deref ptr, use val, incr val, incr ptr"
VECTOR BEFORE = 5,2,7
OUTPUT 5,2,7
VECTOR AFTER = 6,3,8
"#4 deref ptr, incr val, use val, incr ptr"
VECTOR BEFORE = 5,2,7
OUTPUT 6,3,8
VECTOR AFTER = 6,3,8
"#5 incr ptr, deref ptr, use val, incr val"
VECTOR BEFORE = 5,2,7
OUTPUT 2, 7
VECTOR AFTER = 5,3,8
"#6 incr ptr, deref ptr, incr val, use val"
VECTOR BEFORE = 5,2,7
OUTPUT 3, 8
VECTOR AFTER = 5,3,8
*/


/*      cout << "#1 deref ptr, use val, incr ptr" << endl;
      while (first != last)
            cout <<  *first++ << " ";
*/
/*
      cout << "#2 incr ptr, deref ptr, use val"<< endl;
      do
            cout <<  *++first << " ";
       while (first != (last - 1));
*/
/*      cout << "#3 deref ptr, use val, incr val, incr ptr"<< endl;
      while (first != last)
            cout <<  (*first++)++ << " ";
*/
/*      cout << "#4 deref ptr, incr val, use val, incr ptr"<< endl;
      while (first != last)
            cout <<  ++(*first++) << " ";
*/
/*
      cout << "#5 incr ptr, deref ptr, use val, incr val"<< endl;
      do
            cout <<  (*(++first))++ << " ";
       while (first != (last - 1));
*/
/*      cout << "#6 incr ptr, deref ptr, incr val, use val"<< endl;
      do
            cout <<  ++(*(++first)) << " ";
       while (first != (last - 1));
*/
/* this doesn't work*/
      cout << "#3 deref ptr, use val, incr val, incr ptr"<< endl;
      while (first != last)
            cout <<  *(first++)++ << " ";

  // Iterator is used to loop through the vector.
    vector<int>::iterator theIterator;



    // Output contents of theVector.
    cout << endl << "v [ " ;
    for (theIterator = v.begin(); theIterator != v.end();
         theIterator++)
    {
        cout << *theIterator;
        if (theIterator != v.end()-1) cout << ", ";
                                              // cosmetics for the output
    }
    cout << " ]" << endl ;

return (0);
}
0
Comment
Question by:Paullkha
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
10 Comments
 
LVL 2

Author Comment

by:Paullkha
ID: 1198490
Edited text of question.
0
 
LVL 22

Accepted Solution

by:
nietod earned 400 total points
ID: 1198491
>> (*first++)++; How can this work?
The *first returns a reference to (l-value) whatever first originally points to, something like an int or char.  This return value (int or char)  then gets incremented by the last ++.  Thus it says
1. return what first points to.
2. increment first.
3. increment what was returned in step 1.

*(first++)++; Doesn't work? l-val missing ???
right because ++ has higher precendance than *.  This says
1. increment first.
2. increment what was returned in step 1.  Well nothing was returned in step 1.  Step 1 yielded a r-value.

(*(first++))++ should work because it makes the * occur before the last ++.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1198492
cout << "#2 incr ptr, deref ptr, use val"<< endl;
             do
             cout <<  *++first << " ";
             while (first != (last - 1));

That is fine as long as the array holds at least 1 item.   could also be *(++first) or *(first++) and woule be the same.

I'm not sure what to say about the others.  You seem to have a good grasp on it.

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Author Comment

by:Paullkha
ID: 1198493
(*first++)++
I believe the postfix++ and() have higher precedence than *.
>>>> (*first++)++; How can this work?
>>1. return what first points to.
>>2. increment first.
>>3. increment what was returned in step 1.

Why did you start with deref the pointer?
0
 
LVL 22

Expert Comment

by:nietod
ID: 1198494
Yes postfix ++ has higher precendence than * (it has the highest precendence actually), but because the effects of postfix ++ are delayed, it doesn't seem like it.  In

*first++

The ++ is done first, but only in a sense.  
1.  first it returns the original value of first,
2. then it changes first,
3. then * is applied to the original value of first.  (the one returned in 1)

Another way to look at this is to convert it to the equivalent overloaded operator notation.  this would be

operator *(operator++(first,0))

(you can ignore the ",0" there.  It diferentiates between prefix and postfix ++.  It indicates this one is postfix.)
The inner operator ++ saves the original first, then changes first, then returns that saved original value.    That value is then passed to operator *.
0
 
LVL 2

Author Comment

by:Paullkha
ID: 1198495
overloaded operator notation helped alot. thanks
That would mean the following(I changed to NNN to avoid confusion)
1.  (*NNN++)++  =>
operator++( (*NNN++), 0) =>
operator++( (operator *(operator++(NNN,0))),0)

2. operator ++(NNN,0) =>NNN=NNN+1, return old NNN (suppose ptr to old NNN)

3. operator *   =>derefences old NNN <-------???

4. operator ++  =>*old NNN= *old NNN + 1, return *old NNN

WHEREAS
-------

1. ++(*NNN++) =>
operator ++( (*NNN++),1) =>
operator ++( (operator * (operator++(NNN,0))),1)

2. operator ++(NNN,0) =>NNN=NNN+1, return old NNN

3. operator *   =>derefences old NNN

4. operator ++  =>*old NNN= *old NNN + 1, return *old NNN + 1
GOOD???

0
 
LVL 22

Expert Comment

by:nietod
ID: 1198496
That all seems correct to me.

Just as a notational thing, the prefix operator ++ and -- take only 1 parameter.  This is the item they are to operate on.  (The member versions of these take no parameters, as they operate on the object of the class they are part of.)  The postfix versions of these take two parameters.  The 2nd is an int parameter.  The value of this int parameter is not specified, it could be anything, not necessarily 1 or 0.  The existance of this int is so that the two functions have unique signatures, that is so the prefix and postfix functions are different overloads.  The int value isn't really used for any other purpose.
0
 
LVL 2

Author Comment

by:Paullkha
ID: 1198497
Thanks, dummy value for prefix.
Last Question:

//y = why 39 and not 44
...int x = 4, y;
...y = (x+3) * 5 + x++;
x+3 uses the old x value of 4, even though x++ evaluates before (x+3) and changes x's value to 5.
This won't be the same for classes. REGARDLESS of how the post-fix operator is defined, correct? Why?
 I created a "Rational" class to see all this.
...Rational x(1,4), y;
...y = (x+3) * 5 + x++;
x=5/4 , this will than be used in x+3
POSTFIX FUNCTION
const Rational Rational::operator++(int dummy)
{      Rational Tmp = *this;
      numer = numer + denom;
      return (Tmp);
};

0
 
LVL 22

Expert Comment

by:nietod
ID: 1198498
>> x+3 uses the old x value of 4, even though
>> x++ evaluates before (x+3) and changes x's
>> value to 5.
Converting to the operator function notation might have been missleading.  That is exactly what happens when you use these functions with classes that have overloaded the operators.  In that case, it is not missleading, you will get the results that are suggested by the operator function notation (because that is how the expesssion is evaluated.)  Unfortunately, if the expression involves the predefined operators, like the ones for int that appear in your equation, you might not get the same result.  This is because the C++ compiler is not required to update the value changed by the increment  or decrement operators at a specific point--like it would have to do if the increment or decrement was handled by a function.  This allows the compiler much more freedom in how it performs the calculation and therefore allows it much greater opportunity to optimize the calculation.  (These sort of expressions are very ripe for optimization too.)  So in

y = (x+3) * 5 + x++;

the value in x may be updated at any time during the evaluation of the statement.  Thus this sort of expression may yield different results on different compilers.  A classic example of this is

f(int i1, int i2)
    *   *   *
int x = 0;
f(x++,x++);

depending on the compiler the function could be called with (0,0), (1,0), or (0,1).  To make things a little more rational, the standard defines "sequence points" which are places in an expression where the value must be updated, if not updated before then.  In the f(x++,x++);  the first sequence point is the call to the function.  by the time the function is called x must be updated to 2, however the parameters will be passed before that, so the parameters might not be corrrect.  In your example, the only sequence point (I think) was the end of the statement (;), which is always a sequence point.

0
 
LVL 2

Author Comment

by:Paullkha
ID: 1198499
Concise understandable answers, great!
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

670 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question