利用宏定義中的##實現函數模板的作用


利用宏定義的##完成函數模板的定義與調用

宏定義代碼段

#define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \
    static inline uint##_bits##_t ld##_lname##_##_end##_dma(AddressSpace *as, \
                                                            dma_addr_t addr) \
    {                                                                   \
        uint##_bits##_t val;                                            \
        dma_memory_read(as, addr, &val, (_bits) / 8);                   \
        return _end##_bits##_to_cpu(val);                               \
    }                                                                   \
    static inline void st##_sname##_##_end##_dma(AddressSpace *as,      \
                                                 dma_addr_t addr,       \
                                                 uint##_bits##_t val)   \
    {                                                                   \
        val = cpu_to_##_end##_bits(val);                                \
        dma_memory_write(as, addr, &val, (_bits) / 8);                  \
    }

調用宏定義不同的函數,以下代碼實際定義了12個返回類型、函數名、函數內部變量類型不同的函數

DEFINE_LDST_DMA(uw, w, 16, le);
DEFINE_LDST_DMA(l, l, 32, le);
DEFINE_LDST_DMA(q, q, 64, le);
DEFINE_LDST_DMA(uw, w, 16, be);
DEFINE_LDST_DMA(l, l, 32, be);
DEFINE_LDST_DMA(q, q, 64, be);

宏定義中的#與##的含義

在宏定義中#是“字符串化”的意思。出現在宏定義中的#是把跟在后面的參數轉換成一個字符串。

其作用是:將宏定義中的傳入參數名轉換成用一對雙引號括起來參數名字符串。其只能用於有傳入參數的宏定義中,且必須置於宏定義體中的參數名前
例如宏定義代碼

#define M(x)       printf("result = %s",#x)

執行該宏定義

	 int a=1;
	 M(A);

實際結果為

result = A

宏定義中##是一種分隔連接方式,它的作用是先分隔,然后進行強制連接

例如

#define A1(name, type)  type name_##type##_type 或

#define A2(name, type)  type name##_##type##_type

A1(a1, int);  /* 等價於: int name_int_type; */

A2(a1, int);  /* 等價於: int a1_int_type;   */

解釋:

  1. 在第一個宏定義中,"name"和第一個""之間,以及第2個""和第二個"type"之間沒有被分隔,所以預處理器會把name_##type##_type解釋成3段:

“name_”、“type”、以及“_type”,這中間只有“type”是在宏前面出現過

的,所以它可以被宏替換。

  1. 而在第二個宏定義中,“name”和第一個“_”之間也被分隔了,所以

預處理器會把name##_##type##_type解釋成4段:“name”、“_”、“type”

以及“_type”,這其間,就有兩個可以被宏替換了。

  1. A1和A2的定義也可以如下:
#define A1(name, type)  type name_  ##type ##_type 

<##前面隨意加上一些空格>

#define A2(name, type)  type name ##_ ##type ##_type

結果是## 會把前面的空格去掉完成強連接,得到和上面結果相同的宏定義

如果##后的參數本身也是一個宏的話,##會阻止這個宏的展開,也就是只替換一次。

    #define STRCPY(a, b)    strcpy(a ## _p, #b)

    int main()

    {

        char var1_p[20];

        char var2_p[30];

         /* 注意這里 */

        STRCPY(STRCPY(var1,var2),var2);

        /* 這里是否會展開為: strcpy(strcpy(var1_p,"var2")_p,"var2“)?

         * 答案是否定的:

         * 展開結果將是:  strcpy(STRCPY(var1,var2)_p,"var2")

         * ## 阻止了參數的宏展開!

         * 如果宏定義里沒有用到 # 和 ##, 宏將會完全展開

         */

    }  

詳見參考:

http://blog.csdn.net/jiangjingui2011/article/details/6706967


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM