将循环放在C宏中

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

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

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

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

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

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

如果您正在使用GCC,则可以使用它们的statement-expression语法 ,它是C的扩展,而不是标准Cfunction。 语法如下:

 ({ statement; statement; expression; }) 

而上述结果将是最后一个表达式。


在评论中,您表达:

我需要保存xy的新值以便后续调用这个函数foo 。显而易见的方法是将指针传递给xy然后只做一个常规的内联函数。 但是我不想这样做,因为我正在制作一个时间关键的应用程序,我需要xy保留在寄存器中。

你假设xy不会留在寄存器中,这是不好的假设。 这取决于编译器优化代码的能力。 考虑以下:

 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: 

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

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

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

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

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