2009-10-30 57 views
0

我有這個代碼在屏幕上畫一個橢圓,但我不明白這是什麼意思長定義語句,我只想知道如何編寫相同的代碼沒有所有混淆定義語句。這個定義語句是什麼意思?

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

我試圖刪除定義一塊一塊,它不工作,任何建議?

回答

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; 
    } 
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; 
     } 
    } 
} 
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;並用單個宏調用替換它們。這三個語句的順序經常重複,足以使此重構值得。

0

這意味着實際的代碼已經變得太複雜,以至於以前的開發者不得不使用宏來使其更具可讀性。

因爲他們沒有發表評論 - 他們沒有

1

在C,#define S通過預處理,這的確簡單的文本替換編譯器甚至看到代碼之前處理。你有這樣的源文件:

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

這是編譯器實際看到並嘗試進行編譯。

0

對於「它幹什麼」的更高級別的答案,它計算一個近似解的微分方程繪製橢圓; dxt,d2xt,dyt和d2yt變量是變化率(dx/dt,d^{2} x/dt^{2},dy/dt,d^{2} y/dt^{2} , 或多或少)。 incx()和incy()宏一起更新方程的所有變量,以確保它們保持同步。把它看作是信息隱藏的一個非常小的嘗試。