C 如何将函数放入宏中?

C 如何将函数放入宏中?,c,C,正在生成错误,我不知道原因。有人能帮忙吗 编辑:错误如图所示 #define cubem(a) (a * a * a) 因为这样调用了cubem(-a),所以cubem定义应该避免副作用 hw02q2.c:42:31: warning: multiple unsequenced modifications to 'a' [-Wunsequenced] printf("cubem = %d\n", cubem(--a));

正在生成错误,我不知道原因。有人能帮忙吗

编辑:错误如图所示

#define cubem(a) (a * a * a)

因为这样调用了
cubem(-a)
,所以cubem定义应该避免副作用

hw02q2.c:42:31: warning: multiple unsequenced modifications to 'a'
      [-Wunsequenced]
        printf("cubem = %d\n", cubem(--a));
                                 ^~
hw02q2.c:4:19: note: expanded from macro 'cubem'
#define cubem(a) (a * a * a)
以上是gcc c的扩展,请阅读gcc文档的第章

表达式中的语句和声明

原因是

#define cubem(a) \
({ \
    typeof(a) dummy_a = (a); \
    dummy_a * dummy_a * dummy_a; \
})
进行文本替换,并生成

#define cubem(a) (a * a * a)

/* and later using it .... */

printf("cubem = %d\n", cubem(--a));
在一条语句中修改
a
三次。根据C标准,这是未定义的行为

相比之下

printf("cubem = %d\n", (--a * --a * --a));
计算
--a
一次,将结果值传递给
cubef()

如果你真的想“把一个函数放在一个宏中”,那么你可以这样做

int cubef(int a) {
    return a * a * a;
}

/* and later */

printf("cubef = %d\n", cubef(--a));
是什么导致了这种说法

#define cubem(a) cubef(a)
成为

printf("cubem = %d\n", cubem(--a));
这样做的问题是,对于多次使用其参数的宏,它不起作用。比如说

printf("cubem = %d\n", cubef(--a));
原因

int sq(int a) {return a * a;}

#define cubesq(a) (a * sq(a))    /*  uses a more than once
被编译器视为

printf("cubesq = %d\n", cubesq(--a));
再次修改
a
,并导致未定义的行为

原因很简单:预处理器进行文本替换,并修改编译器后期看到的源代码


与其“尝试将函数放入宏”,不如干脆不要使用宏。写函数。使用函数。或者使用宏,但要尊重它们的局限性(即它们不像函数那样工作,即使它们看起来像函数)。

C宏执行文本替换:每个实例都替换为宏定义,宏参数名称替换为实例参数的确切文本

定义为
#define cubem(a)(a*a*a)
cubem
宏将按以下方式展开:

cubem(-a)
->
(-a*--a*--a)

在同一表达式中多次修改
a
具有未定义的行为。您无法通过便携方式解决此问题。如果您足够熟悉并且不介意依赖于不可移植的构造,您可以尝试使用编译器扩展

实现函数并使其内联扩展的正确方法是通过内联函数定义:

printf("cubem = %d\n", (--a * cubesq(--a));
还要注意,宏还有其他问题:

cubem(1+1)
扩展为
(1+1*1+1*1+1)
,计算结果为4,而不是8

为避免此问题,所有宏参数都应加括号:

static inline cubem(int a) { return a * a * a; }
但这个定义仍然不支持有副作用的论点:


cubem(getchar())
将从标准输入读取3个字节。

“生成错误,我不知道原因”。请显示您得到的确切错误,以便我们可以更容易地告诉您原因。它已随错误更新。我没有看到错误,只是警告与宏本身无关。不使用宏也可以得到相同的结果(如果愿意,可以尝试)。看,这不是宏的问题,而是如何使用宏的问题。不要在单个语句中使用前置/后置递增/递减。
typeof
不是标准的C。它是特定于编译器的扩展。用
({
/
})
包装东西也不允许宏在标准C中给出
dummy\u a*dummy\u a*dummy\u a
的值。当我用你的代码替换我的代码时,它可以工作,但我不理解它为什么工作,或者为什么使用“dummy\u a”或“typeof(a)”。你能解释更多吗?很好的尝试,但是如果作为
cubem(dummy_a)
调用,上面的宏将失败。这种练习对于教学目的来说很有趣,但结论应该是编写内联函数。尝试将函数放入宏中的好方法;-)
static inline cubem(int a) { return a * a * a; }
#define cubem(a)  ((a) * (a) * (a))