c语言define中##用法---ffmpeg

来源:互联网 发布:安卓6.0 java模拟器 编辑:程序博客网 时间:2024/06/06 17:38

c语言define中##用法---ffmpeg

#define FUNC(a, depth) a ## _ ## depth ## _c

#define语句中的#是把参数字符串化,##是连接两个参数成为一个整体。
#a指把a当成符号,就是把#后面的看成字符串

#include <stdio.h>

#define FUNC(a, depth) a ## _ ## depth ## _c
#define TESTS(b) #b

void ff_h264_add_pixels4_16_c()
{
printf("this is ff_h264_add_pixels4_16_c function!\n");
    printf("define TESTS(16) is *%s*\n", TESTS(16));
}

int main(int argc, char **argv)
{
FUNC(ff_h264_add_pixels4, 16)();

return 0;
}

#define中 #与##的神奇用法  

code:
#include <stdio.h>


#define f(a,b) a##b 
#define d(a) #a 
#define s(a) d(a) 


void main(void) 

    puts(d(f(a,b))); 
    puts(s(f(a,b))); 



输出结果: 
f(a,b) 
ab


分析:  
##把两个符号连起来 
#a指把a当成符号,就是把#后面的看成字符串

# 和 ## 操作符是和#define宏使用的. 使用# 使在#后的首个参数返回为一个带引号的字符串. 例如, 命令 
    #define to_string(s) #s 
将会使编译器把以下命令 
    printf("%s\n", to_string(Hello World!)); 
理解为 
    printf("%s\n", "Hello World!");
使用##连结##前后的内容. 例如, 命令 
    #define concatenate(x, y) x ## y 
    ... 
    int xy = 10; 
    ... 
将会使编译器把 
    printf("%d\n", concatenate(x, y));
解释为 
    printf("%d\n", xy);
理所当然,将会在标准输出处显示'10'.

puts(d(f(a,b)));  ----> 因为d宏中的参数是另外一个宏,且带##,所以作为参数的宏不展开,相当于 puts(#f(a,b));----->puts("f(a,b)"); 
puts(s(f(a,b))); ----> 因为s宏中的参数是另外一个宏,但不带##,所以作为参数的宏先展开,相当于 puts(s(ab));----->puts(d(ab));---->puts(#ab);---->puts("ab");

#define f(a,b) a##b 
#define d(a) #a -- 以"#"开头的,直接替换,不展开:immediately replaced by the unexpanded actual argument 
#define s(a) d(a) -- 非以"#"开头的,先展开,再替换,也就是一般的情况 

所以就两种情况: 
1,不以"#"开头的,先展开参数a,然后是替换代码:puts(s(f(a,b)));-->puts(s(ab))-->puts(d(ab))-->puts("ab") 
2,以"#"开头的,直接替换,不展开:puts(d(f(a,b)))-->puts("f(a,b)")

#include <stdio.h>

#define DIRECT_LITERAL(a)  #a
#define INDIRECT_LITERAL(a) DIRECT_LITERAL(a)

int main(void)
{
    puts(DIRECT_LITERAL(INDIRECT_LITERAL(a + b)));
    puts(INDIRECT_LITERAL(DIRECT_LITERAL(a + b)));
    return 0;

这其实从编译角度的展开归约也可以理解啊。 

以上代码第一种情况,当预编译器看到DIRECT_LITERAL后查到它是宏定义,定义为#a,此时后面的参数部分就会以#a的形式生成到源文件中。也就是说,预编译后的源文件中,替代第一条语句的就是: 
puts("INDIRECT_LITERAL(a + b)");输出则是INDIRECT_LITERAL(a + b) 
而对于第二条语句,当预编译器看到INDIRECT_LITERAL后查到它是宏定义,定义为DIRECT_LITERAL(a),这时先把它作为DIRECT_LITERAL(DIRECT_LITERAL(a + b))的形式暂存起来,你也可以理解为这个状态是语法树的当中一个叶结点。然后再分析后面的DIRECT_LITERAL后面的参数部分,即:DIRECT_LITERAL(a + b),同样,预编译器会将它归约为"a + b"的形式。这样对于里面的DIRECT_LITERAL(a + b)的形式就完全确定下来了,那么这个值就可以充当叶子结点,即它底下不会再有结点。然后再回到刚才那个状态,DIRECT_LITERAL("a + b")最后就是"\"a + b\""。所以这里输出是"a + b"。 
值得注意的是#a是将参数a转为字符串形式。所以像DIRECT_LITERAL(a)的展开形式是字符串常量"a" 
那么DIRECT_LITERAL("a")展开就是"\"a\""。 


#include <stdio.h>


#define DIRECT_LITERAL(a)  #a
#define INDIRECT_LITERAL(a) DIRECT_LITERAL(a)

#define DIRECT_CAT(a, b)   a##b
#define INDIRECT_CAT(a, b)  DIRECT_CAT(a, b)

int main(void)
{
    puts(DIRECT_LITERAL(INDIRECT_LITERAL(a + b)));
    puts(INDIRECT_LITERAL(DIRECT_LITERAL(a + b)));
    puts(INDIRECT_LITERAL(DIRECT_CAT(INDIRECT_CAT(a, b), INDIRECT_CAT(c, d))));
    puts(INDIRECT_LITERAL(INDIRECT_CAT(DIRECT_CAT(a, b), DIRECT_CAT(c, d))));
    return 0;


0 0
原创粉丝点击