我想知道在普通C( C99 )中是否可以使用包含可在条件表达式中使用的静态变量的宏。
我想出了以下内容(作为一个函数):
char EDGE(unsigned long x)
{
static char up = 0;
static unsigned long v;
if (up && v != x) {
v = x;
return 1;
} else {
v = x;
up = 1;
return 0;
}
}
这正是我想要的,除了它只运行一次(一个错过了使用另一个变量调用函数的缓存值)。
所以我想到了C中的宏和事实,如果这可行,我可以免费获得一个可变缓存,而无需管理任何东西。这是否可以使用普通的旧C?
注意:我希望有一个简单易用的边缘检测“功能”,可以在 if -statement中简单地调用。
答案 0 :(得分:3)
为此,您需要两个宏。第一个用于为特定变量设置边缘函数,第二个用于调用相关函数。
#include <stdio.h>
#define DEF_EDGE(var) static char edge##var(unsigned long var) \
{ \
static char up = 0; \
static unsigned long v = 0; \
if (up && v != var) { \
v = var; \
return 1; \
} else { \
v = var; \
up = 1; \
return 0; \
} \
}
#define EDGE(var) edge##var(var)
DEF_EDGE(x)
DEF_EDGE(y)
int main()
{
unsigned long x = 2, y = 3;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
x=3;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
y=4;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
x=1; y=2;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
return 0;
}
输出:
x=2, y=3 edge(x)=0, edge(y)=0
x=2, y=3 edge(x)=0, edge(y)=0
x=3, y=3 edge(x)=1, edge(y)=0
x=3, y=3 edge(x)=0, edge(y)=0
x=3, y=4 edge(x)=0, edge(y)=1
x=3, y=4 edge(x)=0, edge(y)=0
x=1, y=2 edge(x)=1, edge(y)=1
x=1, y=2 edge(x)=0, edge(y)=0
在每个宏中,##
是连接运算符。这将两个令牌合二为一。
在文件范围内使用第一个宏时:
DEF_EDGE(y)
这扩展为:
static char edgey(unsigned long var)
{
static char up = 0;
static unsigned long v = 0;
if (up && v != var) {
v = var;
return 1;
} else {
v = var;
up = 1;
return 0;
}
}
现在您有一个可以检查y
的边缘条件的函数。
然后当你使用第二个宏时:
EDGE(y)
这扩展为:
edgey(y)
请注意,为此,您设置EDGE功能的每个变量必须具有唯一的名称,无论范围如何。
编辑:
这是另一种没有范围问题的方法:
#include <stdio.h>
static char edge(unsigned long var, unsigned long *v)
{
if (*v != var) {
*v = var;
return 1;
} else {
*v = var;
return 0;
}
}
#define EDGE(var) edge(var, &var##_last)
#define SET_EDGE(var) \
unsigned long var##_last = var;
int main()
{
unsigned long x = 2, y = 3;
SET_EDGE(x);
SET_EDGE(y);
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
x=3;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
y=4;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
x=1; y=2;
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
printf("x=%lu, y=%lu edge(x)=%d, edge(y)=%d\n", x, y, EDGE(x), EDGE(y));
return 0;
}
在这种情况下,在定义相关变量后立即调用SET_EDGE
宏。这将创建另一个变量,并在名称后附加_last
,以跟踪先前的值。当您使用edge
mecro时,此状态变量的地址将传递给EDGE
函数。