c/c++中#和##链接符号的用法

    #include <stdio.h>
    #include <stdlib.h>
    /*
    英语原文:
    In function-like macros, a # operator before an identifier in the replacement-list runs
    the identifier through parameter replacement and encloses the result in quotes,
    effectively creating a string literal. In addition, the preprocessor adds backslashes to escape
    the quotes surrounding embedded string literals, if any, and doubles the backslashes within
    the string as necessary. All leading and trailing whitespace is removed,
    and any sequence of whitespace in the middle of the text (but not inside embedded string literals)
    is collapsed to a single space. This operation is called "stringification".
    If the result of stringification is not a valid string literal, the behavior is undefined.
    */
    /*翻译
    在类函数宏中,替换参数标示符前加#,展开结果实际上是替换参数加双引号的字符串.
    另外,如果参数中有双引号,预处理器替换后会在双引号前加反斜杠\,转义字符。
    如果有反斜杠,对反斜杠加反斜杠转义。
    前置后置空白字符删除,中间连续多个空白字符压缩成一个(字符串除外)。
    这样的操作被称为"字符串化"。假如结果不是有效字符串化,行为没有被定义。
    */
    /*结论:
    1.#在宏替换中产生"参数"这样的字符串
    2.参数中"被展开成\"
    3.参数中\被展开成\    4.参数前置后置空白字符展开时被删除
    5.参数中间的空白序列展开时变成一个,参数为双引号引起来的字符串除外
    6.展开后是无效字符串,行为没有被定义,不同的预处理器有不同的处理方式
    */
    #define FUNCTION_LIKE_MACRO(params) (#params)
    /*
    英语原文:
    A ## operator between any two successive identifiers in the replacement-list runs parameter replacement
    on the two identifiers and then concatenates the result. This operation is called "concatenation" or "token pasting".
    Only tokens that form a valid token together may be pasted: identifiers that form a longer identifier,
    digits that form a number, or operators + and = that form a +=.
    A comment cannot be created by pasting / and * because comments are removed from text
    before macro substitution is considered. If the result of concatenation is not a valid token, the behavior is undefined.
    */
    /*
    翻译:
    ##操作符在两个连续的标示符之间,当宏代替时,结果链接这两个标示符.
    这种操作被称作"链接"或者"符号黏贴".
    只有能形成有效的标示符的符号才能黏贴在一起:标示符形成一个长标示符;数字形成数,+和=形成+=.
    /和*不能形成注释,因为预处理器在宏代替之前都有会把注释去掉。
    假如链接不是有效的符号,这种行为没有定义。
    */
    /*
    1.##链接标示符形成一个标示符
    2.只有形成有效的标示符才能链接
    3.链接结果是无效符号怎样验证
    */
    #define CONCATE_NUMBER(param) (100##param)
    #define CONCATE_ADDEQU(add,equ) add##equ
    #define CONCATE_FUNC(name) FUNC_##name

    //打印函数名字,使用##举例
    void CONCATE_FUNC(myfun)(int var)
    {
        printf("%s[%d]var=%d\n",__FUNCTION__,__LINE__,var);
    }

    int main()
    {
        unsigned int var;
    //# usage=========
        //参数展开为字符串
        printf("str[%s]\n",FUNCTION_LIKE_MACRO(
        printf("str[hello!]\n");//这两条语句结果一样

        //展开后"被转义\"
        printf("str[%s]\n",FUNCTION_LIKE_MACRO("hello!"));
        printf("str[\"hello!\"]\n");

        //这个和英语原文描述的不一样,我理解错了吗?
        printf("str[%s]\n",FUNCTION_LIKE_MACRO(dir1\\sub0));
        printf("str[dir1\\sub0]\n");

        //前后空白字符删除
        printf("str[%s]\n",FUNCTION_LIKE_MACRO( hello ));
        printf("str[hello]\n");

        //中间件空白字符序列压缩成一个,字符串内除外
        printf("str[%s]\n",FUNCTION_LIKE_MACRO(hello world "good morning"));
        printf("str[hello world \"good morning\"]\n");

        //无效字符串,这个不明白,怎样验证
        printf("str[%s]\n",FUNCTION_LIKE_MACRO(\a));
        printf("str[\a]\n");

    //##uase
        printf("concate number(123)=%d\n",CONCATE_NUMBER(123));

        var=11111;
        // var += 22222;
        var CONCATE_ADDEQU(+,=) 22222;
        printf("var=%d\n",var);

        CONCATE_FUNC(myfun)(6890);

        return 0;
    }

c/c++中#和##链接符号的用法,布布扣,bubuko.com

时间: 2024-10-09 20:28:35

c/c++中#和##链接符号的用法的相关文章

Linux中特殊符号的用法

在shell中常用的特殊符号罗列如下: # ;   ;; . , / \\ 'string'| !   $   ${}   $? $$   $* \"string\"* **   ? : ^ $#   [email protected] `command`{}   [] [[]] ()   (()) ||   && {xx,yy,zz,...}~   ~+   ~-   &   \\<...\\>   + - %=   ==   != #井号 (co

嵌入式C语言自我修养 09:链接过程中的强符号和弱符号

9.1 属性声明:weak GNU C 通过 attribute 声明weak属性,可以将一个强符号转换为弱符号. 使用方法如下. void __attribute__((weak)) func(void); int num __attribte__((weak); 编译器在编译源程序时,无论你是变量名.函数名,在它眼里,都是一个符号而已,用来表征一个地址.编译器会将这些符号集中,存放到一个叫符号表的 section 中. 在一个软件工程项目中,可能有多个源文件,由不同工程师开发.有时候可能会遇

java中静态代码块的用法 static用法详解

(一)java 静态代码块 静态方法区别一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的. 静态方法在类加载的时候 就已经加载 可以用类名直接调用比如main方法就必须是静态的 这是程序入口两者的区别就是:静态代码块是自动执行的;静态方法是被调用的时候才执行的.静态方法(1)在Java里,可以定义一个不需要创建对象的方法,这种方法就是

linux中grep和find的用法区别

linux中grep和find的用法区别 本文章详细的介绍了关于在linux中的grep和find两个命令的用法介绍,以及后面总结了它们两年用法区别哦. 先我们来介绍一下关于grep用法和一些小注意事项 使用过程中,使用最多的参数就是 -v ,但是用着并不爽. 比如说,我想查找一个单词“UserService”,但是像”*.svn” 这种文件就不用显示了,我该怎么做呢? 代码如下 复制代码 grep -r "UserService" ./ | grep -v "svn&quo

实例讲解Linux系统中硬链接与软链接的创建

导读 Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).默认情况下,ln命令产生硬链接.硬链接与软链接的区别从根本上要从Inode节点说起,下面就以实例讲解Linux系统中硬链接与软链接的创建,来实际看看Linux中两种链接方式的不同. 首先要弄清楚,在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号.文件属性保存在索引结点里,在访问文件时,索引结点被复制到内存在,从而实现

关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正

首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样感觉的朋友交流也希望高人指点. 首先我们看一下书中关于它们的定义. 引入场景:(1)文件A中定义并初始化变量i(int i = 1), 文件B中定义并初始化变量i(int i = 2).编译链接A.B时会报错b.o:(.data+0x0): multiple definition of `i':a.o:(.d

标准C++中的string类的用法总结【转】

转自(略改动):http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 更全面新颖的说明见:http://www.cplusplus.com/reference/string/string/  说明: 1.size_t 是个unsigned integral type.  2.文中 c字符数组 是指末尾不带'\0'的,注意与 c字符串 的区别 相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC

C/C++中的const真正的用法

const基础知识(用法.含义.好处) intmain() { constint a; intconst b; constint *c; int* const d; constint * const e ; return0; } Intfunc1(const ) 初级理解:const是定义常量==>const意味着只读 含义: //第一个第二个意思一样代表一个常整形数 //第三个c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改) //第四个d常指针(指针变量不能被修改,但

C++中宏的定义与用法(现已被内联函数所代替)

在noip中,宏还是被经常采用,所以这里讲一下,C++中宏的定义与用法 第一种用法——配合条件编译:#define DEBUG 定义一个叫DEBUG的标识符.它应该与#ifdef或#ifndef配合使用.举例如下: #define DEBUG #ifdef DEBUG void print(int v) { cout << v << endl;} #else void print(int) {} #endif 如果符号DEBUG存在,那么编译器会编译上面的.能输出数值的print,