Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does operator precedence in C++ differ for pointers and iterators?

Tags:

c++

stl

The code below demonstrates this difference:

#include <iostream>
#include <string>

int main()
{
        char s[] = "ABCD";
        std::string str(s);

        char *p = s;
        while(*p) {
                *p++ = tolower(*p);          // <-- incr after assignment
        }
        std::cout << s << std::endl;

        std::string::iterator it = str.begin(), end = str.end();
        while(it != end) {
                *it++ = tolower(*it);        // <-- incr before assignment ?
        }
        std::cout << str << std::endl;

        return 0;
}

it produces output:

abcd
bcd

if we separate assignment operation and increment operator:

while(it != end) {
  *it = tolower(*it);        // <-- incr before assignment ?
  it++;
}

the output will be as expected.

What's wrong with the original code?

$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
like image 221
Oleg Razgulyaev Avatar asked May 28 '10 06:05

Oleg Razgulyaev


2 Answers

The problem is that the order of evaluation of arguments of operator= is unspecified. This is according to C++ Standard 5.2.2/8. Consider the following:

*it++ = tolower(*it);

is equal to

operator=( *it++, tolower(*it) );

Now *it++ could be computed before tolower(*it) and vice versa.

like image 59
Kirill V. Lyadvinsky Avatar answered Nov 15 '22 00:11

Kirill V. Lyadvinsky


*it++ = tolower(*it); 
*p++ = tolower(*p);

Both of these lines invoke undefined behaviour. You cannot modify the value of a variable more than once in a single statement (++ modifies once, operator = modifies twice).

So the fact that you get different values is unsurprising.

like image 28
Dean Harding Avatar answered Nov 15 '22 00:11

Dean Harding