2

我正在寻找一种将以下函数结构转换为宏的方法。我知道,这是一个愚蠢且毫无意义的例子,但它说明了这一点,因为我无法给出我的实际源代码。

int foo(int x, int y)
{
  do
  {
    --x;
    ++y;
  }while(x > y);

  return x * y; //note that x and y have changed values here.
}

这样我就可以在 main 或其他一些函数中调用该函数,如下所示:

int next_x = foo(x,y);

我似乎无法在这里得到 100% 正确的语法。这是我糟糕的尝试:

#define FOO(x,y)      \
(                     \
  do                  \
  {                   \
    --x;              \
    ++y;              \
  }while(x < y),      \
  x                   \
)                     

最后x的原因是,理论上我可以做到这一点

int next_x = FOO(x,y);

但相反,我得到一个语法错误,我不知道为什么。任何帮助,将不胜感激。

================================================

附加信息

我还应该注意,我还有其他相应结构的宏:

#define INIT(x,y)   
(   
  x = //something,
  y = //something
)

#define NEXT_INT(x,y)    \
(                        \
  INIT(x,y),             \
  get_next_num(x,y)      \            //Note, this is an inline function call , not a macro.
 )

#define NEXT_FLOAT(x,y,temp)         \
(                                    \
  temp = NEXT_INT(x,y),              \
  temp ? temp * 1.23456 : FLT_MIN    \
)                                    

所以,我可以并且已经做了以下事情:

float my_flt = NEXT_FLOAT(x,y,temp);
4

3 回答 3

3

C 语法只允许用逗号运算符 ( ,) 分隔表达式。do ... while()不是表达式,而是语句,因此将其用作逗号运算符的值是错误的。

一般来说,内联函数应该优先于宏来执行一些内联​​计算。它们更容易实现、更不容易出错并且更容易维护。在极少数情况下,内联函数会失败而宏会成功。

确实没有一个安全的宏来实现您的目标,但一种解决方法是将您想要更新的变量作为宏参数传递。

#define FOO(x, y, result) \
    do { \
        do { \
            --x; \
            ++y; \
        } while(x > y); \
        result = x * y; \
    } while(0)

如果您使用的是 GCC,则可以使用它们的语句表达式语法,它是 C 的扩展,而不是标准的 C 功能。语法如下:

({ statement; statement; expression; })

上面的结果将是最后一个表达式。


在评论中,您表示:

我需要保存新值xy后续调用这个函数foo..这样做的明显方法是将指针传递给x然后y只创建一个常规的内联函数。但是我不想这样做,因为我正在制作一个时间紧迫的应用程序,我需要xy保留在寄存器中。

您假设x并且y不会留在寄存器中,这是一个不好的假设。这取决于编译器优化代码的能力的质量。考虑以下:

static inline int foo (int *x, int *y) {
    do {
        --*x;
        ++*y;
    } while (*x > *y);
    return *x**y;
}

int main (int argc, char *argv[]) {
    int x = argc+1;
    int y = argc;
    foo(&x, &y);
    return 0;
}

使用 编译时gcc -O1,结果为:

main:
.LFB14:
        movl    %edi, %edx
.L2:
        movl    %edi, %eax
        addl    $1, %edx
        subl    $1, %edi
        cmpl    %edx, %eax
        jg      .L2
        movl    $0, %eax
        ret
.LFE14:

您将观察到没有指针值取消引用,这正是您想要发生的。

于 2013-07-25T19:23:45.583 回答
2

您不能将do/while循环用作表达式,因此您需要在括号内使用块,如下所示:

编辑:这是一个 GCC 扩展,而不是标准 C

#define FOO(x,y)    \
({                  \
  do                \
  {                 \
    --x;            \
    ++y;            \
  }while(x > y);    \
  x;                \
})
于 2013-07-25T19:12:40.020 回答
0

这里的一个问题是多行宏\在每一行的末尾都需要 a。

于 2013-07-25T19:08:02.650 回答