c语言 # 操作符的三种用法

1.前提

本文所介绍的 “#” 操作符的三种用法均发生在预编译阶段, 这点对于理解 “#”,操作符是非常重要的。

2. 第一种用法:#include #define #if …

如下示例,这种用法是最长见的用法,在此不过多描述。

/* 头文件包含 */
#include 

/* 宏定义 */
#define INCLUDE_vTaskPrioritySet             1
#define INCLUDE_uxTaskPriorityGet            1
#define INCLUDE_vTaskDelete                  1

/* 条件编译 */
#if ( configUSE_PREEMPTION == 0 )
    #define queueYIELD_IF_USING_PREEMPTION()
#else
    #if ( configNUMBER_OF_CORES == 1 )
        #define queueYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()
    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
        #define queueYIELD_IF_USING_PREEMPTION()    vTaskYieldWithinAPI()
    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
#endif

3. 第二种用法:将宏定义的参数转化为一个字符串

通过如下示例,一看即可明白。

3.1 示例1

  • 如下c示例:
    #include 
    #define STRING(s)  #s
    
    int main (void)
    {
    	printf ("%s\n", STRING(hello));
    	return 0;
    }
    
  • 将上面代码进行预编译:
    为防止预编译后的代码太大,注释了 #include
    gcc -E hello.c -o hello.i
    
    # 0 "hello.c"
    # 0 ""
    # 0 ""
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 0 "" 2
    # 1 "hello.c"
    
    int main (void)
    {
    	printf ("%s\n", "hello");
    	return 0;
    }
    
  • 总结:由示例可看出,对宏参数使用 # 修饰,预编译器会将宏参数先加上 “”,然后再复制到调用位置。

    与不加 # 相比,预编译器多了加 “” 的操作

3.2 示例2

如下示例是linux内核中的一句内嵌汇编,用于在c代码中插入 nop 指令,关于gcc内嵌汇编,有兴趣可以看我的另外一篇文章https://blog.csdn.net/dmf_fff/article/details/134587580

#define __nops(n)	".rept	" #n "\nnop\n.endr\n"
#define nops(n)		asm volatile(__nops(n))

3.2.1 .rept 和 .endr

上面代码中的 .rept.endr,是一组汇编伪指令,由汇编器处理,可以看做是将 .rept.endr之间的指令复制多份,有兴趣可以看汇编器手册 7.82
c语言 # 操作符的三种用法_第1张图片

3.2.2 预编译示例

  • 预编译前

    #define __nops(n)	".rept	" #n "\nnop\n.endr\n"
    #define nops(n)		asm volatile(__nops(n))
    
    int main (void)
    {
    	asm volatile(__nops(7));
    	return 0;
    }
    
  • 预编译后

    int main (void)
    {
    	asm volatile(".rept " "7" "\nnop\n.endr\n");
    	return 0;
    }
    

4. 第三种用法:拼接宏参数

看如下示例:

  • 预编译前
    #define BFQ_BFQQ_FNS(name)						\
    void bfq_mark_bfqq_##name(struct bfq_queue *bfqq);			\
    void bfq_clear_bfqq_##name(struct bfq_queue *bfqq);			\
    int bfq_bfqq_##name(const struct bfq_queue *bfqq);
    
    BFQ_BFQQ_FNS(just_created);
    BFQ_BFQQ_FNS(busy);
    BFQ_BFQQ_FNS(wait_request);
    BFQ_BFQQ_FNS(non_blocking_wait_rq);
    BFQ_BFQQ_FNS(fifo_expire);
    BFQ_BFQQ_FNS(has_short_ttime);
    BFQ_BFQQ_FNS(sync);
    BFQ_BFQQ_FNS(IO_bound);
    BFQ_BFQQ_FNS(in_large_burst);
    BFQ_BFQQ_FNS(coop);
    BFQ_BFQQ_FNS(split_coop);
    BFQ_BFQQ_FNS(softrt_update);
    #undef BFQ_BFQQ_FNS
    
  • 预编译后
    void bfq_mark_bfqq_non_blocking_wait_rq(struct bfq_queue *bfqq); 
    void bfq_clear_bfqq_non_blocking_wait_rq(struct bfq_queue *bfqq);
    int bfq_bfqq_non_blocking_wait_rq(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_fifo_expire(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_fifo_expire(struct bfq_queue *bfqq);
    int bfq_bfqq_fifo_expire(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_has_short_ttime(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_has_short_ttime(struct bfq_queue *bfqq);
    int bfq_bfqq_has_short_ttime(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_sync(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_sync(struct bfq_queue *bfqq);
    int bfq_bfqq_sync(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_IO_bound(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_IO_bound(struct bfq_queue *bfqq);
    int bfq_bfqq_IO_bound(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_in_large_burst(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_in_large_burst(struct bfq_queue *bfqq);
    int bfq_bfqq_in_large_burst(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_coop(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_coop(struct bfq_queue *bfqq);
    int bfq_bfqq_coop(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_split_coop(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_split_coop(struct bfq_queue *bfqq);
    int bfq_bfqq_split_coop(const struct bfq_queue *bfqq);;
    
    void bfq_mark_bfqq_softrt_update(struct bfq_queue *bfqq);
    void bfq_clear_bfqq_softrt_update(struct bfq_queue *bfqq);
    int bfq_bfqq_softrt_update(const struct bfq_queue *bfqq);;
    

你可能感兴趣的:(c语言,开发语言)