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

本文详细介绍了C语言中#操作符在预编译阶段的三种常见用法:包括头文件包含、宏参数字符串化以及宏参数拼接。通过实例展示了这些用法如何影响代码生成和性能优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前提

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

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

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

/* 头文件包含 */
#include <stdint.h>

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

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

3.2 示例2

如下示例是linux内核中的一句内嵌汇编,用于在c代码中插入 nop 指令,关于gcc内嵌汇编,有兴趣可以看我的另外一篇文章https://blog.youkuaiyun.com/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
在这里插入图片描述

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);;
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值