C 这个定义语句是什么意思?
我有一段代码可以在屏幕上画一个椭圆,但我不明白长的define语句意味着什么,我只想知道如何编写相同的代码,而不让define语句混淆C 这个定义语句是什么意思?,c,c-preprocessor,C,C Preprocessor,我有一段代码可以在屏幕上画一个椭圆,但我不明白长的define语句意味着什么,我只想知道如何编写相同的代码,而不让define语句混淆 #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 =
#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();
}
}
}
#定义incx()x++,dxt+=d2xt,t+=dxt
#定义incy()y--,dyt+=d2yt,t+=dyt
空心椭圆(整数xc、整数yc、整数rx、整数ry、整数颜色)
{
int x=0,y=ry;
长rx2=(长)rx*rx,ry2=(长)ry*ry;
长临界值1=-(rx2/4+rx%2+ry2);
长临界值2=-(ry2/4+ry%2+rx2);
长临界值3=-(ry2/4+ry%2);
长t=-rx2*y;//e(x+1/2,y-1/2)-(a^2+b^2)/4
长dxt=2*ry2*x,dyt=-2*rx2*y;
长d2xt=2*ry2,d2yt=2*rx2;
(y>=0&&x如果您只想删除它,请通过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;
}
}
}
#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;
}
}
}
void椭圆(int-xc、int-yc、int-rx、int-ry、int-color)
{
int x=0,y=ry;
长rx2=(长)rx*rx,ry2=(长)ry*ry;
长临界值1=-(rx2/4+rx%2+ry2);
长临界值2=-(ry2/4+ry%2+rx2);
长临界值3=-(ry2/4+ry%2);
长t=-rx2*y;//e(x+1/2,y-1/2)-(a^2+b^2)/4
长dxt=2*ry2*x,dyt=-2*rx2*y;
长d2xt=2*ry2,d2yt=2*rx2;
当(y>=0&&x时,假设逗号是分号,因为这实际上就是它们的用途。宏可以写得更直接一些,如下所示:
#define incx() do { x++; dxt += d2xt; t += dxt; } while (0)
#define incy() do { y--; dyt += d2yt; t += dyt; } while (0)
#define incx() x++, dxt += d2xt, t += dxt
if (t + ry2*x <= crit1 || t + rx2*y <= crit3)
incx();
更直接的是,这三条语句以分号结尾。使用do{}while(0)
loop,这是一种将多条语句转换为一条大语句的常用习惯用法
#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();
}
}
}
(虽然它看起来像一个循环,但它只会执行一次,然后结束,因为while(0)
条件被保证为false。这个技巧的目的是在宏之后需要一个分号,所以您可以像普通函数一样使用它:incx();
或incy();
)
不管怎么说,这些宏的要点是将重复出现的x++;dxt+=d2xt;t+=dxt;
替换为一个宏调用。这三个语句的序列经常重复,足以使重构变得有价值。这意味着实际的代码已经变得太复杂,无法读取,以前的开发人员我求助于使用宏来提高可读性
由于他们没有留下注释-他们在C中失败了,#define
由预处理器处理,它在编译器看到代码之前进行简单的文本替换。您有一个如下的源文件:
#define incx() do { x++; dxt += d2xt; t += dxt; } while (0)
#define incy() do { y--; dyt += d2yt; t += dyt; } while (0)
#define incx() x++, dxt += d2xt, t += dxt
if (t + ry2*x <= crit1 || t + rx2*y <= crit3)
incx();
这就是编译器实际看到并试图编译的内容。对于“它在做什么”的更高层次的答案,它是计算一个微分方程的近似解来绘制椭圆;dxt、d2xt、dyt和d2yt变量是变化率(dx/dt、d^{2}x/dt^{2}、dy/dt、d^{2}y/dt 2},或多或少)。incx()和incy()宏一步一步地将方程中的所有变量一起更新,以确保它们保持同步。可以将其视为信息隐藏的一次非常小的尝试