簡體   English   中英

學習C#定義語句(MACROS)

[英]Learning C #define statement (MACROS)

我目前正在閱讀Stephen G. Kochan的“用C編程”,偶然發現了一個練習(第13章,第5章):

編寫宏SHIFT來執行與程序12.3shift功能相同的目的。

這是程序12.3

unsigned int shift (unsigned int  value, int  n)
{
    if ( n > 0 )     // left shift 
        value <<= n;
    else             // right shift 
        value >>= -n;

    return value;
}

這是我當前的代碼:

#include <stdio.h>
#define SHIFT(n)  (n) > 0 ? << (n) : >> (-(n))

unsigned int w1 = 0177777u, w2 = 0444u;
printf ("%o\t%o\n" w1 SHIFT(5), w1 << 5);

如果n為正,則宏中的條件應左移,否則應右移。

因此, printf兩個參數應該具有相同的值,但是我一直收到編譯器錯誤。

如果我將#define更改為:

#define SHIFT(n)  << n

...該代碼有效,但是我不能右移帶有負號。

SHIFT的條件版本有什么問題?

讓我們假設這段代碼:

#include <stdio.h>

#define SHIFT(n)  (n) > 0 ? << (n) : >> (-(n))
// #define SHIFT(n)  << n

int main(int argc, char *argv[])
{
  unsigned int w1 = 0177777u, w2 = 0444u;
  printf("%o\t%o\n", w1 SHIFT(5), w1 << 5);
}

使用#define SHIFT(n) << n您的代碼可以按預期工作,因為宏只是文本替換。 因此,編譯器實際上看到了這一點:

  printf("%o\t%o\n", w1 << 5, w1 << 5);

代替這個:

  printf("%o\t%o\n", w1 SHIFT(5), w1 << 5);

但是隨着#define SHIFT(n) (n) > 0 ? << (n) : >> (-(n)) #define SHIFT(n) (n) > 0 ? << (n) : >> (-(n))編譯器看到以下內容:

  printf("%o\t%o\n", w1 (5) > 0 ? << (5) : >> (-(5)), w1 << 5);

這在語法上是錯誤的,沒有任何意義。

你需要這個:

#include <stdio.h>

#define SHIFT(value, n)  ... left as an exercise....

unsigned int shift(unsigned int  value, int  n)
{
  if (n > 0)     // left shift 
    value <<= n;
  else             // right shift 
    value >>= -n;

  return value;
}    

int main(int argc, char *argv[])
{
  unsigned int w1 = 0177777u, w2 = 0444u;
  printf("%o\t%o\n", SHIFT(w1, 5), shift(w1, 5));    // test case for positive shift value
  printf("%o\t%o\n", SHIFT(w1, -5), shift(w1, -5));  // test case for negative shift value
}

首先,請注意,此功能本身是出於學習目的而設計的-絕不會在函數或宏后面隱藏諸如移位之類的基本內容。 這樣做只會降低程序的可讀性。

第一步是修復函數​​,以便處理n為零的情況。 主要是,當表達式value >> -0出現時,我們不想冒險讓編譯器陷入麻煩。 (更重要的是,這還為異國/虛構的補語和符號和幅度系統提供了可移植性。)

inline unsigned int shift (unsigned int value, int n)
{
    if (n == 0)           // don't shift
        ;
    else if ( n > 0 )     // left shift 
        value <<= n;
    else /* n < 0 */      // right shift 
        value >>= -n;

    return value;
}

inline是對編譯器的微優化提示,不要生成任何開銷函數調用代碼。現代編譯器可能不需要。)

然后像函數一樣簡單地實現宏。 在任何類似於函數的宏中,都需要在每個宏參數以及宏本身周圍使用括號。

由於宏沒有return語句,因此必須確保它始終求值到所需的值。 這將要求我們使用條件運算符而不是if-else。 由於?:不提供if - else if - else選項,因此它必須是嵌套的?:表達式。

#define SHIFT(value, n) ( (n)==0 ? (value) :                  \
                                   ((n)>0 ? (value) <<= (n) : \
                                            (value) >>= -(n)) )

這將是避免類似函數的宏的主要原因之一。 除了具有清晰易讀的功能之外,我們還有這種幾乎不可讀的混亂。 笨拙的程序員甚至可能很想把它寫成一條可怕的單行:

#define SHIFT(value, n) ((n)==0?(value):((n)>0?(value)<<=(n):(value)>>=-(n))) // BAD CODE

嘗試這個。

#define SHIFT(n) ((n) > 0 ? << (n) : >> (-(n))) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM