1

I'm trying to assign a variable using the result of a function.

MAT2 _m_pow2(const MAT2 A, int p, MAT2 tmp)
{
  MAT2 out;
  int it_cnt, k, max_bit;
#define Z(k) (((k) & 1) ? tmp : out)

  out = m_get2(A.m, A.n);
  tmp = m_get2(A.m, A.n);
  if(p == 0)
    out = m_ident2(out);
  else if(p > 0)
  {
    it_cnt = 1;
    for(max_bit = 0; ; max_bit++)
      if((p >> (max_bit+1)) == 0)
        break;
      tmp = m_copy2(A);
      for(k = 0; k < max_bit; k++)
      {
        Z(it_cnt+1) = m_mlt2(Z(it_cnt), Z(it_cnt));
        it_cnt++;
        if(p & (1 << (max_bit-1)))
        {
          Z(it_cnt+1) = m_mlt2(A, Z(it_cnt));
          it_cnt++;
        }
        p <<= 1;
      }
      if(it_cnt & 1)
        out = m_copy2(Z(it_cnt));
  }
  return out;
#undef Z
}

The function m_mlt2() returns MAT2. I am getting these errors:

error: lvalue required as left operand of assignment

Z(it_cnt+1) = m_mlt2(Z(it_cnt), Z(it_cnt));

and

error: lvalue required as left operand of assignment

Z(it_cnt+1) = m_mlt2(A, Z(it_cnt));

What am I doing wrong? If it needs more detais, please, feel free to ask. Thanks in advance!

P.S. I know I will get downvotes, I tried to do my best formulating this question.

  • Welcome to the site! Check out the [tour](https://stackoverflow.com/tour) and the [how-to-ask page](https://stackoverflow.com/help/how-to-ask) for more about asking questions that will attract quality answers. You can [edit your question](https://stackoverflow.com/posts/48814957/edit) to include more information. See [this answer](https://stackoverflow.com/a/6966331/2877364) for one possibility. – cxw Feb 15 '18 at 19:35
  • 2
    Try making this into a [mcve], please! <3 – SIGSTACKFAULT Feb 15 '18 at 19:36
  • 2
    Your `Z` macro does not generate an lvalue, as the error says. – vanza Feb 15 '18 at 19:37
  • 4
    Could use `#define Z(k) (((k) & 1) ? &tmp : &out)` ... `*Z(it_cnt+1) = m_mlt2(A, *Z(it_cnt));` it should compile and sadly win the wrath of other programmers. – chux - Reinstate Monica Feb 15 '18 at 19:42
  • @machine_1I forgot to remove that. Thanks! – Thiago Cavalcante Feb 15 '18 at 19:55
  • did you even look up what `error: lvalue required as left operand of assignment` means? –  Feb 15 '18 at 19:56
  • @chux, I did like you proposed and it worked, no syntax error. However, the return is not like I was expecting. It seems that there is something wrong in the second time (loop), `it_cnt = 2`, and `Z(it_cnt+1)` returns a wrong value. Is there anything changing the address of `Z(it_cnt+1)` or something else? – Thiago Cavalcante Feb 15 '18 at 21:56
  • @ThiagoCavalcante Yes, but there are better, clearer ways to code than that. – chux - Reinstate Monica Feb 15 '18 at 21:58
  • @ThiagoCavalcante [is not like I was expecting](https://stackoverflow.com/questions/48814957/why-am-i-getting-errors-assigning-a-variable-but-the-variables-have-the-same-typ?noredirect=1#comment84637827_48814957) --> You have not said what the results were, nor stated the expectations, not inputs. Posted code does not compile. You have good answers here to one of code's problems, yet SO is not for repetitive iterations of code. Work it out the best you can. In the future post a [MCVE] – chux - Reinstate Monica Feb 16 '18 at 03:06

2 Answers2

1

(((k) & 1) ? tmp : out) is not an l-value. The result is the value of either tmp, or out, NOT the variable name.

You might try something like this;

  MAT2 out[2];
  int it_cnt, k, max_bit;
  out[1] = tmp;
#define Z(k) out[(((k) & 1))]
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
cleblanc
  • 3,678
  • 1
  • 13
  • 16
1

The Z macro expands to a ternary expression. So:

Z(it_cnt+1) = m_mlt2(Z(it_cnt), Z(it_cnt));

expands to (in part):

(((it_cnt+1) & 1) ? tmp : out) = m_mlt2(...);

As a result, you have a ternary expression ( ? : ) on the left side of the assignment =.

An lvalue is (very roughly speaking) a value you can assign to. As this answer points out, in C (not C++), the ternary operator does not produce an lvalue. Instead, as @cleblanc mentioned, it gives you the values of the expressions.

Edit This is C++ code, so your best bet is probably to switch to C++. An example modified from this question:

#include<stdio.h>

int main()
{
 int a=5,b=6;
 ( ((a>b) & 1) ? a : b ) = 42;
 printf("%d %d\n", a, b);
 return 0;
}

In C:

$ gcc foo.c && ./a
foo.c: In function ‘main’:
foo.c:6:26: error: lvalue required as left operand of assignment
  ( ((a>b) & 1) ? a : b ) = 42;
                          ^
$

In C++:

$ g++ foo.cpp && ./a
5 42
$

If you can't use C++, I'd use @chux's idea, quoted here for posterity: #define Z(k) (((k) & 1) ? &tmp : &out) ... *Z(it_cnt+1) = m_mlt2(A, *Z(it_cnt));.

cxw
  • 16,685
  • 2
  • 45
  • 81