如何在宏中放置函数?

时间:2017-01-29 10:01:34

标签: c

#include <stdio.h>
// 2.1
#define subm(a,b) (a - b)
#define cubem(a) (a * a * a)
#define minm minf
#define oddm oddf
//---------------------------Given Code------------------------------------
int subf(int a, int b) {
    return a - b;
}
int cubef(int a) {
    return a * a * a;
}
int minf(int a, int b) {
    if (a <= b) {
        return a;
    } else {
        return b;
    }
}
int oddf(int a) {
     if (a % 2 == 0) {
        return 0;
    } else {
        return 1;
    }
}
//----------------------------Given Code----------------------------------
// 2.2
int main() {
    int a = 5;
    int b = 7;

    subf(a,b);printf("subf = %d\n", subf(a,b));
    subm(a,b);printf("subm = %d\n", subm(a,b));
    subf(a++,b--);printf("subf = %d\n", subf(a++,b--));
    subm(a++,b--);printf("subm = %d\n", subm(a++,b--));

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

    minf(a,b);printf("minf = %d\n", minf(a,b));
    minm(a,b);printf("minm = %d\n", minm(a,b));
    minf(--a,--b);printf("minf = %d\n", minf(--a,--b));
    minm(--a,--b);printf("minm = %d\n", minm(--a,--b));

    oddf(a);printf("oddf = %d\n", oddf(a));
    oddm(a);printf("oddm = %d\n", oddm(a));
    oddf(a++);printf("oddf = %d\n", oddf(a++));
    oddm(a++);printf("oddm = %d\n", oddm(a++));
}

我在将功能放入宏中时遇到了一些麻烦。我的教授希望我们了解如何处理宏和函数。我这样做的方式基本上就像你在这里看到的那样,但是它没有正常工作,或者至少

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

产生错误,我不知道为什么。有人可以帮忙吗?

编辑:错误如图所示

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)

3 个答案:

答案 0 :(得分:4)

原因是

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

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

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

进行文本替换,并生成

printf("cubem = %d\n", (--a * --a * --a));

在一个语句中修改a三次。根据C标准,这是未定义的行为。

相比之下,

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

/* and later */

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

评估--a一次,将结果值传递给cubef()

如果你真的想“在宏中放置一个函数”,那就做一些像

这样的事情
#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));

编译器将其视为

printf("cubem = %d\n", (--a * cubesq(--a));

再次修改a一次并导致未定义的行为。

原因很简单:预处理器执行TEXT SUBSTITUTION并修改编译器后期阶段看到的源代码。

而不是“尝试将函数放入宏中”,而不是使用宏。写功能。使用功能。或者使用宏,但要尊重它们的局限性(即它们不像函数一样工作,即使它们看起来像函数)。

答案 1 :(得分:1)

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

您定义为cubem的{​​{1}}宏将以这种方式扩展:

#define cubem(a) (a * a * a) - &gt; cubem(--a)

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

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

a

另请注意,宏有其他问题:

static inline cubem(int a) { return a * a * a; } 扩展为cubem(1 + 1),其评估为4而不是8。

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

(1 + 1 * 1 + 1 * 1 + 1)

但是这个定义仍然不支持带副作用的论据:

#define cubem(a) ((a) * (a) * (a)) 将从标准输入中读取3个字节。

答案 2 :(得分:-1)

由于你像这样调用cubem(--a),你的立方体定义应该避免副作用。

#define cubem(a) \
({ \
    typeof(a) dummy_a = (a); \
    dummy_a * dummy_a * dummy_a; \
})

上面是gcc c扩展,阅读gcc文档,章节

  

表达式中的陈述和声明