宏 - 表达式不可分配

时间:2017-01-03 11:19:22

标签: c macros c-preprocessor

编译时出现此错误:

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

我不知道为什么会这样说,我找不到任何错误。 这是代码:

#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);
}

6 个答案:

答案 0 :(得分:7)

宏执行文本替换。因此,ProdottoAumentato(10, 20);将替换为以下内容:

10++; 10 * 20;;

10++无效。你不能修改文字,这就是错误信息&#34;表达不可分配的内容&#34;指的是。

  

如何增加该值呢?

您需要将值分配给变量才能对其进行修改。请参阅维托里奥·罗密欧的答案,作为一个例子。

答案 1 :(得分:5)

宏是任何想象力的功能。宏中的X以文本方式替换为宏的第一个参数; Y也是如此 - 它被第二个参数替换。

表达式10++无效,原因与10 = 10+1无效的原因相同。但是,这是宏扩展后得到的表达式,这是编译器通过其表达式告诉你的表达式不可分配的#34;错误。

答案 2 :(得分:2)

回复Andr1x的评论:

  

如何增加该值呢?

你可以使用一个功能:

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

可以如下调用:

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

我不能。这是大学的练习,我需要在宏观中做所有事情。

这很难过,因为这对宏来说是一个可怕的用例。然而,如果你想使用宏,你的参数必须评估为&#34;可递增的#34; (即左值)

这里是最安全的&#34;使用宏执行此操作的方法:

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

然后你可以打电话:

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

将对其进行预处理:

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?

答案 3 :(得分:0)

您没有解释您真正想要的内容以及您(错误地)使用宏的原因。我猜这是因为你认为宏运行得更快。

然后只需定义一个inline函数,如

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

最多optimizing compilers(例如gcc -Wall -O2如果使用GCC ....),这与您尝试过的宏一样快,因为编译器会执行inline expansion

如果由于某种奇怪的原因你还想使用宏和C预处理器,请检查其输出,例如通过运行gcc -C -E yourcode.c > yourcode.i,然后查看(使用less或某些源代码编辑器等寻呼机)到包含预处理表单的生成的yourcode.i中。

根据经验,您通常需要在宏定义中添加额外的括号:

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

否则ProdottaAumentato(u+3,v+5)将不会像您希望的那样展开,因为预处理是纯粹的文本操作。

您也可以使用statement exprs(有用的GCC扩展程序)并拥有

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

您可以定义两个全局变量; int xx, yy;并且

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

使用comma operator

答案 4 :(得分:0)

你想要的是

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

int main(void)
{
  int x = 10;

  x = ProdottoAumentato(x, 20);

  /* x is 220 here. */
}

在实际C编译之前,预处理器将上述源代码转换为:

int main(void)
{
  int x = 10;

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


}

这个

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

是逗号运算符排序的两个表达式。首先评估左侧(带序列点),然后评估右侧。后一个值作为整个表达式的结果被“返回”。

答案 5 :(得分:0)

你究竟想要这个宏做什么?您正在对常量执行操作,结果不会归因于任何变量。

如果你只想拿两个数字,先添加一个数字再乘以第二个数字,你应该尝试

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

另一方面,如果你想增加一个变量,然后将它乘以另一个变量,你应该尝试

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

对于像你试图拉动的常数一样,这将无法使用。