zoukankan      html  css  js  c++  java
  • 有意思的C宏

    在Linux内核嵌入式代码等传统的C代码里,会有一些难以识别的宏定义我记得在eCos, UBoot, FFmpeg有一些比较BT的宏定义,很难读懂。对于C++程序员来说,最好将这种难读的宏定义转成inline函数或模板函数本章对这些较难的重定义进行汇总。

    1. ; 在宏定义中指定义类型参数
       1: #define FPOS_TO_VAR(fpos, typed, var)                    (var) = (typed)((fpos).__pos)
       2: #define VAR_TO_FPOS(fpos, var)                           (fpos).__pos = (var)

    此句在faac的代码里可以见到,其特殊之处是以类型名作为参数,而且是用宏定义一行赋值语句像如下的调用:

      

       1: uint64_t  ret;
       2: FPOS_TO_VAR(fpos,  uint64_t, ret);
       3:  
       4: uint64_t ret;
       5: ret = (uint64_t) (fpos.__pos);
       6:  
    一般可以对宏定义作换行显示,换行后会更清晰易懂一些:

       1: #define FPOS_TO_VAR(fpos, typed, var)        
       2:                    (var) = (typed)((fpos).__pos)
    2 . 宏定义取结构偏移

    这种用法似乎在uCosII中用到,记不清了。举例来说,我们知道一个struct(类型为T)中有一个变量为v,那么由v的地址来得到T的指针呢?

    #define S_OFFSET(T,v)      (&((T*)0)->v)
    
    
       1: struct ABC
       2: {
       3:     int a;
       4:     char b;
       5:     int c;
       6: };
       7:  
       8: int main()
       9: {
      10:     unsigned int offset = (unsigned int) S_OFFSET(ABC, b);
      11:     return 0;
      12: }

    主要是分析一下(&((T*)0)->v)是个什么意思,相当于以下几种代码:
    1. T* p = (T*) 0;  // 把0地址强转为一个T*  
    2. void* offset = &p->v; // 由于变量p的地址为0,所以成员变量v的偏移就是其地址 
    T* p = (T*) 0;  // 把0地址强转为一个T*
    void* offset = &p->v; // 由于变量p的地址为0,所以成员变量v的偏移就是其地址
    得到上述偏移之后怎么用呢?在函数传递的过程中,只需要一个v的指针,就可以反推出其所在的结构的地址而offset一般不方便指定为一个固定值,因为不同环境下的padding可能不一致,也不方便扩展。
    1. void* p = ...;  
    2. T* t = (T*) (p - offset); 
    void* p = ...;
    T* t = (T*) (p - offset);
    3 . 宏定义中的连接符##

    这也是一种比较特殊的用法,在eCos3中经常用到用于替换一个完整名字(类型名、函数变量名) 的一部分。以下再种写法等效,请仔细体会:

    my_type_t   var1;
    my_type_t   var2;

       1: struct my_type_t
       2: {
       3:         int a;
       4:         char b;
       5: };
       6:  
       7: #define    MY_TYPE(T,  name)       
       8:         T  var##name
       9:  
      10: MY_TYPE(my_type_t, 1);
      11: MY_TYPE(my_type_t, 2);
      12:  
      13: int main()
      14: {
      15:         unsigned int offset = (unsigned int) S_OFFSET(my_type_t, b);
      16:         var1.a = 10;
      17: }

    4 . 宏定义中的字符串#
       1: define  MYSTR(value)   #value
       2: int main()
       3: {
       4:         char* cc = MYSTR(hello);
       5: }
    相当于

    char* cc = "hello";

    友情链接:C/C++宏的奇巧淫技

  • 相关阅读:
    3. docker-compose实战--ghost app
    3. nacos服务发现
    1. nacos初识, 和eureka的比较, 在docker上安装nacos
    2.nacos服务配置中心
    如何将PHP对象数组转换成普通数组
    php 通过变量 来调用函数
    linux svn
    Sublime text 3安装svn插件
    php 字符串 定界符 json_last_error()
    centos7 rm -rf 删除文件的找回
  • 原文地址:https://www.cnblogs.com/pianist/p/3286325.html
Copyright © 2011-2022 走看看