我有这个代码在屏幕上绘制一个椭圆,但我不明白它是什么意思长定义语句,我只想知道如何编写相同的代码,而没有所有混淆定义语句。
#define incx() x++, dxt += d2xt, t += dxt
#define incy() y--, dyt += d2yt, t += dyt
void ellipse(int xc, int yc, int rx, int ry, int color)
{
int x = 0, y = ry;
long rx2 = (long)rx*rx, ry2 = (long)ry*ry;
long crit1 = -(rx2/4 + rx%2 + ry2);
long crit2 = -(ry2/4 + ry%2 + rx2);
long crit3 = -(ry2/4 + ry%2);
long t = -rx2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4
long dxt = 2*ry2*x, dyt = -2*rx2*y;
long d2xt = 2*ry2, d2yt = 2*rx2;
while (y>=0 && x<=rx)
{
pixel(xc+x, yc+y, color);
if (x!=0 || y!=0)
pixel(xc-x, yc-y, color);
if (x!=0 && y!=0)
{
pixel(xc+x, yc-y, color);
pixel(xc-x, yc+y, color);
}
if (t + ry2*x <= crit1 || //e(x+1,y-1/2) <= 0
t + rx2*y <= crit3) //e(x+1/2,y) <= 0
incx();
else if (t - rx2*y > crit2) //e(x+1/2,y-1) > 0
incy();
else
{
incx();
incy();
}
}
}
我试图逐个删除定义并且它不起作用,有什么建议吗?
答案 0 :(得分:3)
如果您只想删除它,请通过cpp
:
cpp cpp.c > cppout.c
给了我
# 1 "cpp.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpp.c"
void ellipse(int xc, int yc, int rx, int ry, int color)
{
int x = 0, y = ry;
long rx2 = (long)rx*rx, ry2 = (long)ry*ry;
long crit1 = -(rx2/4 + rx%2 + ry2);
long crit2 = -(ry2/4 + ry%2 + rx2);
long crit3 = -(ry2/4 + ry%2);
long t = -rx2*y;
long dxt = 2*ry2*x, dyt = -2*rx2*y;
long d2xt = 2*ry2, d2yt = 2*rx2;
while (y>=0 && x<=rx)
{
pixel(xc+x, yc+y, color);
if (x!=0 || y!=0)
pixel(xc-x, yc-y, color);
if (x!=0 && y!=0)
{
pixel(xc+x, yc-y, color);
pixel(xc-x, yc+y, color);
}
if (t + ry2*x <= crit1 ||
t + rx2*y <= crit3)
x++, dxt += d2xt, t += dxt;
else if (t - rx2*y > crit2)
y--, dyt += d2yt, t += dyt;
else
{
x++, dxt += d2xt, t += dxt;
y--, dyt += d2yt, t += dyt;
}
}
}
您可能遇到的问题是在宏中使用逗号运算符。我建议您使用;
替换逗号,并将if
部分放在{}
内,并使用换行符。 (这里我手动插入{和},然后在Emacs中使用M-x replace-string RET , RET ; C-Q C-J
,然后C-M-\
缩进该区域。)
if (t + ry2*x <= crit1 ||
t + rx2*y <= crit3) {
x++;
dxt += d2xt;
t += dxt;
} else if (t - rx2*y > crit2) {
y--;
dyt += d2yt;
t += dyt;
} else {
x++;
dxt += d2xt;
t += dxt;
y--;
dyt += d2yt;
t += dyt;
}
答案 1 :(得分:3)
假装逗号是分号,因为它实际上是它们的用途。宏可以像这样写得更直接:
#define incx() do { x++; dxt += d2xt; t += dxt; } while (0)
#define incy() do { y--; dyt += d2yt; t += dyt; } while (0)
嗯,更简单的是,这三个陈述以分号结束。使用do { } while (0)
循环不太常见,这是将多个语句转换成一个大语句的常用习惯。
(虽然它看起来像一个循环,它只执行一次然后结束,因为while (0)
条件保证为false。这个技巧的目的是在宏之后需要分号,所以你只使用它像普通函数一样:incx();
或incy();
)
无论如何,这些宏的重点是重复出现x++; dxt += d2xt; t += dxt;
并用一次宏调用替换它们。这三个语句的序列经常重复,足以使这种重构变得有价值。
答案 2 :(得分:1)
在C中,#define
由预处理器处理,在编译器甚至看到代码之前进行简单的文本替换。你有一个像这样的源文件:
#define incx() x++, dxt += d2xt, t += dxt
if (t + ry2*x <= crit1 || t + rx2*y <= crit3)
incx();
预处理器会将incx()
的每次出现替换为x++, dxt += d2xt, t += dxt
,因此会导致:
if (t + ry2*x <= crit1 || t + rx2*y <= crit3)
x++, dxt += d2xt, t += dxt;
这是编译器实际看到并尝试编译的内容。
答案 3 :(得分:0)
#define
由预处理器评估,并简单地将第一个项的任何实例替换为该行的其余部分。所以代码等同于以下内容:
void ellipse(int xc, int yc, int rx, int ry, int color)
{
int x = 0, y = ry;
long rx2 = (long)rx*rx, ry2 = (long)ry*ry;
long crit1 = -(rx2/4 + rx%2 + ry2);
long crit2 = -(ry2/4 + ry%2 + rx2);
long crit3 = -(ry2/4 + ry%2);
long t = -rx2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4
long dxt = 2*ry2*x, dyt = -2*rx2*y;
long d2xt = 2*ry2, d2yt = 2*rx2;
while (y>=0 && x<=rx)
{
pixel(xc+x, yc+y, color);
if (x!=0 || y!=0)
pixel(xc-x, yc-y, color);
if (x!=0 && y!=0)
{
pixel(xc+x, yc-y, color);
pixel(xc-x, yc+y, color);
}
if (t + ry2*x <= crit1 || //e(x+1,y-1/2) <= 0
t + rx2*y <= crit3) //e(x+1/2,y) <= 0
x++, dxt += d2xt, t += dxt;
else if (t - rx2*y > crit2) //e(x+1/2,y-1) > 0
y--, dyt += d2yt, t += dyt;
else
{
x++, dxt += d2xt, t += dxt;
y--, dyt += d2yt, t += dyt;
}
}
}
答案 4 :(得分:0)
这意味着实际代码变得太复杂而无法阅读,之前的开发人员已经使用宏来使其更具可读性。
由于他们没有发表评论 - 他们失败了
答案 5 :(得分:0)
对于“它在做什么”的更高级答案,它计算了微分方程的近似解以绘制椭圆; dxt,d2xt,dyt和d2yt变量是变化率(dx / dt,d ^ {2} x / dt ^ {2},dy / dt,d ^ {2} y / dt ^ {2} , 或多或少)。 incx()和incy()宏将等式的所有变量一起更新,以确保它们保持同步。可以把它想象成一种非常小的信息隐藏尝试。