这个定义语句是什么意思?

时间:2009-10-30 03:13:33

标签: c c-preprocessor

我有这个代码在屏幕上绘制一个椭圆,但我不明白它是什么意思长定义语句,我只想知道如何编写相同的代码,而没有所有混淆定义语句。

#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();
        }
    }
}

我试图逐个删除定义并且它不起作用,有什么建议吗?

6 个答案:

答案 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()宏将等式的所有变量一起更新,以确保它们保持同步。可以把它想象成一种非常小的信息隐藏尝试。