对宏定义中出现的##运算符和#运算符的说明

本文详细介绍了C语言宏定义中的##和#运算符。##用于连接两个参数形成一个新符号,例如Conn(123,456)得到123456。#则将参数转换为字符串,如ToChar(1)得到'1'。通过实例展示了这两个运算符的用法和效果,包括在字符串化和符号连接中的应用。" 106618793,8686725,web网页制作实践——HTML与CSS实现,"['HTML', 'CSS', 'Web开发', '网页设计', '上机实践']

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

#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x

x##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); 结果就是n=123456;
char* str = Conn("asdf", "adf")结果就是 str = "asdfadf";
怎么样,很神奇吧

再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many characters in constant :P

最后看看#x,估计你也明白了,他是给x加双引号
char* str = ToString(123132);就成了str="123132";

最后留几个小试验给大家去测测:

#define Dec(x,y) (x-y)
int n = Dec( A(123,1), 1230);
n = Conn(123, Conn(123,332) );
char* str = A("12", ToString( Dec(3,1));
结果会如何呢? 嘿嘿嘿嘿~

参考:

C语言之#define用法(宏定义命令)

==============================================================

3.#运算符
    #的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。例如:
        #define _STR(s)     #s
        #define WARN_IF(EXP)    \
        do{ if (EXP)    \
            fprintf(stderr, "Warning: " #EXP "\n"); }   \
        while(0)

        那么实际使用中会出现下面所示的替换过程:
        WARN_IF (divider == 0);

     被替换为

        do
     {
            if (divider == 0)
          fprintf(stderr, "Warning" "divider == 0" "\n");
        } while(0);
 这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。
 
 再例如下面的例子:
     #define  FILL(a)   {a, #a}

     enum IDD{OPEN, CLOSE};
     typedef struct MSG{
        IDD id;
        const char * msg;
     }MSG;

     MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
     相当于:
       MSG _msg[] = {{OPEN, "OPEN"},
                     {CLOSE, "CLOSE"}}; 

  4.##运算符
    ##运算符用于把参数连接到一起。
 预处理程序把出现在##两侧的参数合并成一个符号。
 看下面的例子:

            #define NUM(a,b,c) a##b##c
            #define STR(a,b,c) a##b##c

            main()
            {
                printf("%d\n",NUM(1,2,3));
                printf("%s\n",STR("aa","bb","cc"));
            }

        最后程序的输出为:
                 123
                 aabbcc
 再看下面的例子:
 struct command
    {
     char * name;
     void (*function) (void);
    };

    #define COMMAND(NAME) { NAME, NAME ## _command }

   // 然后你就用一些预先定义好的命令来方便的初始化一个command结构的数组了:

    struct command commands[] = {
     COMMAND(quit),
     COMMAND(help),
     ...
    }

    COMMAND宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以n个##符号连接 n+1个Token。比如:
    #define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

    typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
    // 这里这个语句将展开为:
    // typedef struct _record_type name_company_position_salary;

参考:

C语言宏定义总结


附加:

_T()、_TEXT()宏中也出现过这两个运算符。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值