神奇的 ## 符号
发布日期:2021-06-28 22:05:13 浏览次数:2 分类:技术文章

本文共 3858 字,大约阅读时间需要 12 分钟。

原文链接地址:http://starryalley.homelinux.net/blog/index.php?/archives/1134-Token-Concatenation-in-C-preprocessor.html

使用程式碼來介紹比較快:

#define foo() bar      foo()baz           ==> bar baz      not           ==> barbaz  所以加上’##’的用法,就可以達成barbaz,以下是範例:   
#define COMMAND(NAME)  { #NAME, NAME ## _command }   
struct  command commands[] = {  
  COMMAND (quit),  
  COMMAND (help),  
  //...   
};  
#define COMMAND(NAME) { #NAME, NAME ## _command }struct command commands[] = { COMMAND (quit), COMMAND (help), //...}; 經過C preprocessor處理後,會展開如下:
struct  command commands[] = {  
  { “quit”, quit_command },  
  { “help”, help_command },  
  //...   
};  
struct command commands[] = { { “quit”, quit_command }, { “help”, help_command }, //...}; 其中#NAME是Stringification的功能,所以配合’##’ token concatenation,我們可以結合兩個param。

之前在trace ffmpeg source code,其中竟然找不到put_pixels4_c()這類 function的definition,ctags找不到,grep好久也沒有。原來就是利用了token concatenation來產生的function。

以下是 節錄ffmpeg 0.5 source 裡面的一段code,用了C preprocessor token concatenation(其中省略了不相關的幾行程式碼):

  1. #define PIXOP2(OPNAME, OP) /   
  2. static   void  OPNAME ## _pixels2_c(uint8_t *block,  const  uint8_t *pixels,  int  line_size,  int  h){/  
  3.   //...    
  4.   OP(*((uint16_t*)(block)), AV_RN16(pixels));/  
  5.   //...   
  6. }/  
  7. static   void  OPNAME ## _pixels4_c(uint8_t *block,  const  uint8_t *pixels,  int  line_size,  int  h){/  
  8.   //...   
  9.   OP(*((uint32_t*)(block)), AV_RN32(pixels));/  
  10.   //...   
  11. }/  
  12. //...   

在下面則使用這段code的方式:

  1. #define op_avg(a, b) a = rnd_avg32(a, b)   
  2. #define op_put(a, b) a = b   
  3. PIXOP2(avg, op_avg)  
  4. PIXOP2(put,op_put)  
  5. #undef op_avg   
  6. #undef op_put   
  7. //from ffmpeg0.5, libavcodec/dsputil.c   

使用gcc -E來展開preprocessor動作後,Line 1261和1262,呼叫PIXOP2的macro,就會自動產生新的function definition:

  1. static   void  avg_pixels2_c(uint8_t *block,  const  uint8_t pixels,  int  line_size,  int  h){  
  2.     ((uint16_t*)(block )) = rnd_avg32(*((uint16_t*)(block )), AV_RN16(pixels ));  
  3. }  
  4. static   void  avg_pixels4_c(uint8_t *block,  const  uint8_t pixels,  int  line_size,  int  h){  
  5.     ((uint32_t*)(block )) = rnd_avg32(*((uint32_t*)(block )), AV_RN32(pixels ));  
  6. }  
  7. static   void  put_pixels2_c(uint8_t *block,  const  uint8_t pixels,  int  line_size,  int  h){  
  8.     ((uint16_t*)(block )) = AV_RN16(pixels );  
  9. }  
  10. static   void  put_pixels4_c(uint8_t *block,  const  uint8_t pixels,  int  line_size,  int  h){  
  11.     ((uint32_t*)(block )) = AV_RN32(pixels );  
  12. }  

又學到一招,這code還真簡潔明瞭,不需要重複寫很多同質性的function definition。

有關C preprocessor的token concatenation介紹請參考 。

转载地址:https://blog.csdn.net/yfh1985sdq/article/details/5699838 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:FFMPEG coping with webcam
下一篇:char, signed char,unsigned char, short int unsigned short int, int数据类型取值问题

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月24日 16时40分28秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

Android中高级面试必知必会,积累总结 2019-04-29
Activity的6大难点,你会几个?跳槽薪资翻倍 2019-04-29
Android-App的设计架构经验谈,系列篇 2019-04-29
Android-Camera内存问题剖析,安卓系列学习进阶视频 2019-04-29
Android-Camera内存问题剖析,小白也能看明白 2019-04-29
Android事件分发机制及设计思路,先收藏了 2019-04-29
Android事件分发机制收藏这一篇就够了,不吃透都对不起自己 2019-04-29
Android内存泄漏总结,offer拿到手软 2019-04-29
Android内存泄漏总结,成功拿下大厂offer 2019-04-29
Android初级开发是如何一步步成为高级开发?源码+原理+手写框架 2019-04-29
最新BAT大厂面试者整理的Android面试题目模板,看看这篇文章吧! 2019-04-29
最详细的docker中安装并配置redis,好文推荐 2019-04-29
月薪20k+的Android面试都问些什么?3面直接拿到offer 2019-04-29
月薪20k+的Android面试都问些什么?深夜思考 2019-04-29
月薪20k+的Android面试都问些什么?绝对干货 2019-04-29
有了这些中高端面试专题-大厂还会远吗?工作感悟 2019-04-29
有了这些中高端面试专题-大厂还会远吗?我先收藏为敬 2019-04-29
有了这些中高端面试专题-大厂还会远吗?系列篇 2019-04-29
来看看移动端小程序技术的前世今生!讲的明明白白! 2019-04-29
来看看这份超全面的《Android面试题及解析》,大厂面经合集 2019-04-29