3

I have a question that I'd love to google but I have no idea on what to ask her/she/it (google :) )

Having found assignments like this in several example codes (this particular one originated here where they copied the code from the Numerical Recipes in C p. 508) on the net.

I tried to understand the usage of the assignment in the following line:

wr = (wtemp = wr) * wpr - wi * wpi + wr;

as far as my own understanding of programming logic goes, I would translate it to

wtemp = wr;
wr = wtemp * wpr - wi * wpi + wr;

is that correct? or should it be wpr * wpr - wi [...]? or something completely different :D?

(according to wikipedia the assignment operator returns a reference to the assignee, which according to the free dictionary - i checked to be sure - is the value which something is being assigned to)

Asmodiel
  • 1,002
  • 1
  • 12
  • 21

2 Answers2

6

The value of the expression a = b is the value of a after assignment, so:

wr = (wtemp = wr) * wpr - wi * wpi + wr;

is equivalent to:

wtemp = wr;
wr = wtemp * wpr - wi * wpi + wr;

or:

wtemp = wr;
wr = wr * wpr - wi * wpi + wr;

Reference:

6.5.16 Assignment operators

An assignment expression has the value of the left operand after the assignment (...).

Community
  • 1
  • 1
md5
  • 23,373
  • 3
  • 44
  • 93
  • 1
    +1; although it's cute to write code like this, take very good care as undefined behaviour is never too far away; e.g. `wr = wr++` is undefined in C. – Bathsheba Aug 19 '13 at 14:07
  • ok thanks. When you move the ``wtemp = wr;`` assignment to a line above, wtemp and wpr are obviously the same so there is no difference. thanks :) – Asmodiel Aug 19 '13 at 14:07
  • 2
    @Bathsheba: And it is not very readable. So obviously this kind of statements should be avoided in production code. – md5 Aug 19 '13 at 14:08
  • @Bathsheba: which part might be undefined? ``wr = wr++`` would be translated to ``wr = wr += 1;`` wouldn't it? – Asmodiel Aug 19 '13 at 14:09
  • 2
    @Asmodiel: No, it won't. C standard says it is undefined behavior, since the value of `wr` is both modified and accessed without sequence point. [Google it. ;)](http://stackoverflow.com/questions/949433/could-anyone-explain-these-undefined-behaviors-i-i-i-i-i-etc) – md5 Aug 19 '13 at 14:12
2

@md5 has the correct answer, but I've seen this misused so many times I felt the need to comment further. In almost all circumstances doing assignments like this is wrong. Not "won't compile" wrong, but "I can't tell if that's what you really meant to do" wrong. It immediately requires the reader to stop and think hard about what you are doing. If there's a practical way to avoid doing assignments mid-process use it. Create a temporary variable, break the evaluation into stages, whatever.

Now, there are times when this is actually helpful. As an example, here is some code which calls a very slow function (canFreelyStop), but only if it actually must. At the same time it is doing some evaulation of system state:

        //determine whether transport motor should be running and make it happen
        bool canStop = true;
        if (    m_requestErrorStop
             || (    !m_receiving                       // not receiving new items from upstream.
                  && ((canStop = canFreelyStop()) != 0) // can stop without damaging anything (!=0 to avoid compiler warning)
                )
           )
        {
           //ready to turn it off
           ...
        }
        else if (!canStop)
        {
           //only failed to stop due to documents in transit.  Wait a "cycle" and check again
           ...
        }

It's not trivial to rework this code to eliminate the internal assignment (it's also relying on short circuit evaluation). This is one of the only conditionals I've ever written where internal assignment was actually better than the alternative. If anyone comes along wanting to change/debug this code I want them to have to stop and think hard about it.

Speed8ump
  • 1,307
  • 10
  • 25