Increment pointer and dereference order in C ++

I am teaching students in C ++ and recently ran into an issue with pointer arithmetic with array names. The main thing I am confused with is the statement

T min_value = *begin++; 

      

Cplusplus tells me that the ++ operator has higher precedence than the * dereference operator, so my guess is that the start is incremented first and then dereferenced. In addition, this site confirms that when you pass an array name to a function, it becomes a pointer to the address of the first element, element [0]. However, when I run the code below in Visual Studio, it looks like the min_value is 1.5 at first, which seems to contradict what I think is the order of operations.

I think it should be:

  • add a start pointer to element [1] (second in the array)
  • dereference pointer value
  • set min_value equal to the 2nd element of the array.

However, my experiment shows that something else is happening instead:

  • reversal indicator value
  • set min_value equal to the 1st element of the array
  • pointer to pointer to next element

Can someone please clarify this?

// Problem #3: Please write the implementation of min() function and max() function..

#include <iostream> 
using namespace std; 
template<typename T> 

T min(T* begin, T* end) 
{ 
        T min_value = *begin++; 
        while(begin != end) // You can use for-loop too. 
        { 
                if( *begin < min_value) 
                        min_value = *begin; 
                begin++; 
        } 
        return min_value; 
} 
template<typename T> 
T max(T* begin, T* end) 
{ 
        T max_value = *begin++; 
        while(begin != end) 
        { 
                if( *begin > max_value) 
                        max_value = *begin; 
                begin++; 
        } 
        return max_value; 
} 
int main() 
{ 
        double arr[] = {    1.5, 4.5, 3.5, 2.5, 5.5 }; 
        int values[] = {    1, 2, 3, 4, -1, 5 }; 
        cout << "min of arr[] is : " << min(arr, arr + 5) << endl; 
        cout << "min of values[] is : " << min(values, values + 6) << endl; 
        cout << "max of arr[] is : " << max(arr, arr + 5) << endl; 
        cout << "max of values[] is : " << max(values, values + 6) << endl; 
}

      

+3


source to share


3 answers


Priority is just a rule for how the code should be parsed. ++

in first place, and *

second. But when the code is executed, you must consider what the statements are actually doing.

In your case, the following happens:

  • Copy in progress begin

    .
  • The original is enlarged.
  • A copy is returned.
  • The copy is dereferenced .
  • A copy is assigned min_value

    .

This is how the post-increment operator works, and also how you write the operator when you overload it for your own types:



T operator++(int)
{
    T copy = *this;
    ++(*this);
    return copy;
}

      


In fact, in the case of the built-in post-increment operator, the increment does not have to be step 2. It can also happen at a later point if the observed behavior is the same. For example, nothing prevents the compiler from incrementing the original value after it has returned a copy. Of course, you couldn't do such a thing in your own, overloaded operator.

+2


source


This expression

T min_value = *begin++; 

      

can be represented as follows:

auto temp = begin;
T min_value = *temp;
++begin;

      

As per C ++ standard (5.2.6 Increment and Decrement)

1 Value of expression postfix ++ value of its Operand . [Note: the resulting value is a copy of the original -end note] ... The evaluation of the expression ++ is sequenced before changing the operand object.



In general, function definitions are incorrect because the range specified by begin

and end

may be empty, and the beginning may point outside the valid range. In this case, you can neither start nor dereference it.

So, it would be more correct to write, for example, the following path

T * min( T* begin, T* end ) 
{
    T *min_value = begin;

    if ( begin != end )
    {
        while( ++begin != end )
        { 
            if( *begin < *min_value ) min_value = begin; 
        } 
    }

    return min_value; 
} 

      

In this case, the function call will look like

cout << "min of arr[] is : " << *min(arr, arr + 5) << endl;
                               ^^^

      

+1


source


The return value of an operator and precedence should not be confused.

The first is what the operator returns, the second is when something happens.

So, if you have:

T min_value = *begin++;

      

This is how it works:

  • operator++

    - it increments the pointer but returns the original pointer.
  • operator*

    - dereferences a pointer returned earlier, returns the T it pointed to.
  • operator=

    keeps the left side to the right side, returns the right side.

You are not using the last return value, but in theory you can.

Note that in # 2, you are using the return from # 1, rather than referring to the pointer again.

+1


source







All Articles