Bit Twiddling Behaviour

D

Danny Woods

Hi all,

I've inherited an unusual piece of code that behaves slightly oddly.
A method on a class mutates the value of an integer instance
variable by bitwise or-ing it with the result of a function that also
(conditionally) manipulates that same piece of state. Reducing it to a
simple test case:

---
#include <iostream>

using std::cout;
using std::endl;

class BitTwiddle
{
private:
int m_field;
public:
BitTwiddle() { m_field = 2; }
int twiddle() { return m_field |= mutate(); }
int mutate() { return m_field = 1; }
};

int main(void)
{
BitTwiddle bt;
cout << "Twiddled: " << bt.twiddle() << endl;
return 0;
}
---

With Visual C++ and Cygwin g++ on Windows, this code produces the string
'Twiddled: 1', but on the Mac and on Linux (both g++), this produces the
string 'Twiddled: 3'.

So the question: what does the Standard have to say about this? Are any
of the compilers wrong, or has this wandered off into 'undefined'
territory?

Cheers,
Danny.
 
F

Fred

Hi all,

I've inherited an unusual piece of code that behaves slightly oddly.
A method on a class mutates the value of an integer instance
variable by bitwise or-ing it with the result of a function that also
(conditionally) manipulates that same piece of state.  Reducing it to a
simple test case:

---
#include <iostream>

using std::cout;
using std::endl;

class BitTwiddle
{
private:
  int   m_field;
public:
  BitTwiddle() { m_field = 2; }
  int twiddle() { return m_field |= mutate(); }
  int mutate() { return m_field = 1; }

};

int main(void)
{
  BitTwiddle    bt;
  cout << "Twiddled: " << bt.twiddle() << endl;
  return 0;}

---

With Visual C++ and Cygwin g++ on Windows, this code produces the string
'Twiddled: 1', but on the Mac and on Linux (both g++), this produces the
string 'Twiddled: 3'.

So the question: what does the Standard have to say about this?  Are any
of the compilers wrong, or has this wandered off into 'undefined'
territory?

I believe this is undefined.

"a |= b" is the same as "a = a | b"

In your case, b modifies a. So which "a" should
be used in "a | b" ? Should it be the value before b modifies
it, or the value after b modifies it?
 
J

joseph cook

  BitTwiddle() { m_field = 2; }
  int twiddle() { return m_field |= mutate(); }
  int mutate() { return m_field = 1; }

};

So the question: what does the Standard have to say about this?  Are any
of the compilers wrong, or has this wandered off into 'undefined'
territory?

It is undefined behavoir. This is because the call to "|=" can
evaluate the "mutate" first, or the left hand side "m_field" first.
It just has to evaluate them both before calling "|=".

Joe Cook
 
J

Juha Nieminen

Sean said:
It's mystifying to me how compilers can have things like
-Weffc++ but no -Wundefined-behavior.

At least gcc warns about some undefined behavior (when -Wall is
specified). For example this line:

int b = ++a + ++a;

gives me:

warning: operation on 'a' may be undefined
 
J

James Kanze

It is undefined behavoir. This is because the call to "|="
can evaluate the "mutate" first, or the left hand side
"m_field" first. It just has to evaluate them both before
calling "|=".

It's unspecified, not undefined. By definition, "m_field |=
mutate()" is "m_field = m_field | mutate()". The order of
evaluation of the operands to | is unspecified, but there's no
undefined behavior, and the results have to correspond to one
possible ordering.

(And I know, this is nit-picking, since in practice, it comes
out to the same thing---you don't know what the results of the
expression are.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top