-2

I get this error when compiling:

macro.c:11:2: error: expression is not assignable
    ProdottoAumentato(10, 20);

I don't know why it says this, I can't find any errors. Here's the code:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#define ProdottoAumentato(X, Y)    X++; X * Y;

int main(void) {

    ProdottoAumentato(10, 20);

    printf("\nEnd\n");
    return(0);
}
alk
  • 69,737
  • 10
  • 105
  • 255

6 Answers6

7

Macros perform textual replacement. So ProdottoAumentato(10, 20); gets replaced with the following:

10++; 10 * 20;;

10++ is not valid. You can't modify a literal, which is what the error message "expression is not assignable" is referring to.

How can I increment that value then?

You need to assign the value to a variable to modify it. See Vittorio Romeo's answer for an example of this.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
5

Macro is not a function by any stretch of imagination. X in the macro is textually substituted with the first parameter of the macro; same is done for Y - it is replaced with the second parameter.

The expression 10++ is invalid, for the same reason that 10 = 10+1 is invalid. However, this is the expression that you get after macro expansion, which is what the compiler tells you by its "expression is not assignable" error.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Replying to Andr1x's comment:

How can I increment that value then?

You could use a function:

int ProdottoAumentato(int* x, int y)
{
    ++(*x);
    return (*x) * y;
}

Which can be called as follows:

int my_x = 10;
int res = ProdottoAumentato(&my_x, 20);
assert(my_x == 11);
assert(res == 11 * 20);

I can't. It's an exercise for university, I'm required to do everything in a macro.

That's sad, because this is a terrible use case for a macro. Nevertheless, if you want to use a macro, your arguments must evaluate to symbols which are "incrementable" (i.e. lvalues).

Here's the "safest" way of doing this with a macro:

#define ProdottoAumentato(result, X, Y) \ 
    do { ++(X); result = (X) * (Y); } while(0)

Then you can call:

int my_x = 10;
int res;
ProdottoAumentato(res, my_x, 20);
assert(my_x == 11);
assert(res == 11 * 20);

Which will be preprocessed to:

int my_x = 10;
int res; 
do { ++(my_x); res = (my_x) * (20); } while(0);
assert(my_x == 11);
assert(res == 11 * 20);

(Why am I using do while?)

Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
0

You don't explain what you really want and why you are (incorrectly) using a macro. I'm guessing that it is because you think that macros run faster.

Then just define an inline function like

static inline int ProdottoAumentato(int x, int y) 
  { return (x+1)*y; }

with most optimizing compilers (e.g. gcc -Wall -O2 if using GCC....), this is as fast as your attempted macro, because the compiler will do inline expansion.

If for some strange reason you still want to use macro and the C preprocessor, check its output, e.g. by running gcc -C -E yourcode.c > yourcode.i then look (with a pager like less or some source code editor) into the generated yourcode.i containing the preprocessed form.

As a rule of thumb, you generally need to add extra parenthesis in macro definitions:

#define ProdottoAumentato(X,Y) ((X)+1)*(Y))

otherwise ProdottaAumentato(u+3,v+5) won't be expanded like you wish, since the preprocessing is a purely textual operation.

You might also use statement exprs (a useful GCC extension) and have

#define ProdottoAumentato(X,Y) ({int _x = (X); int _y = (Y); (++_x * _y)})

You might define two global variables; int xx, yy; and have

#define ProdottoAumentato(X,Y) ((xx=(X),((yy=(Y)),((++xx)*yy))

using the comma operator.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thank you very much. Unfortunately it's a very, very weird exercises I got from my teacher that had to be done just with use of a macro and no functions whatsoever. – poweruser621 Jan 03 '17 at 11:57
0

You want is

#define ProdottoAumentato(X, Y) ((X)++, (X) * (Y))

int main(void)
{
  int x = 10;

  x = ProdottoAumentato(x, 20);

  /* x is 220 here. */
}

Before the actual C compilation, the pre-processor converts the above source code into:

int main(void)
{
  int x = 10;

  x = ((x)++, (x) * (20));


}

This

  ((x)++, (x) * (20))

are two expressions sequenced by the comma operator. First the left side is evaluated (with a sequence point), then the right side. The latter value is "returned" as the result of the whole expression.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
alk
  • 69,737
  • 10
  • 105
  • 255
0

What exactly you want this macro to do? You are performing operations over constants and the results are not attributed to any variable.

If you just want to take two numbers, add one to the first and multiply by the second, you should try

#define ProdottoAumentato(X, Y) (X+1)*Y

If, on other hand you want to increment a variable, and multiply it by another variable you should try

#define ProdottoAumentato(X, Y) X++; Y*=X

And that will never work with constants like you tried to pull.

Luiz Menezes
  • 749
  • 7
  • 16