代码之家  ›  专栏  ›  技术社区  ›  supercat

命名全局范围的一次性标识符

  •  1
  • supercat  · 技术社区  · 14 年前

    有时,在使用宏生成代码时,有必要创建具有全局作用域的标识符,但这些标识符对于创建它们的直接上下文之外的任何内容都没有真正的用处。例如,假设有必要在编译时将数组或其他索引资源分配到不同大小的块中。

    /* Produce an enumeration of some story-book characters, and allocate some
       arbitrary index resource to them.  Both enumeration and resource indices
       will start at zero.
    
       For each name, defines HPID_xxxx to be the enumeration of that name.
       Also defines HP_ID_COUNT to be the total number of names, and
       HP_TOTAL_SIZE to be the total resource requirement, and creates an
       array hp_starts[HP_ID_COUNT+1].  Each character n is allocated resources
       from hp_starts[n] through (but not including) hp_starts[n+1].
    */
    
    /* Give the names and their respective lengths */
    #define HP_LIST \
      HP_ITEM(FRED, 4) \
      HP_ITEM(GEORGE, 6) \
      HP_ITEM(HARRY, 5) \
      HP_ITEM(RON, 3) \
      HP_ITEM(HERMIONE, 8) \
      /* BLANK LINE REQUIRED TO ABSORB LAST BACKSLASH */
    
    #define HP_ITEM(name, length) HPID_##name,
    typedef enum { HP_LIST HP_ID_COUNT} HP_ID;
    #undef HP_ITEM
    
    #define HP_ITEM(name, length) ZZQ_##name}; enum {ZZQX_##name=ZZQ_##name+(length)-1,
    enum { HP_LIST HP_TOTAL_SIZE};
    #undef HP_ITEM
    
    #define HP_ITEM(name, length) ZZQ_##name,
    const unsigned char hp_starts[] = { HP_LIST HP_TOTAL_SIZE};
    #undef HP_ITEM
    
    #include "stdio.h"
    
    void main(void)
    {
      int i;
    
      printf("ID count=%d Total size=%d\n",HP_ID_COUNT,HP_TOTAL_SIZE);
      for (i=0; HP_ID_COUNT > i; i++) /* Reverse conditional to avoid lt sign */
        printf("  %2d=%3d/%3d\n", i, hp_starts[i], hp_starts[i+1]-hp_starts[i]);
      printf("IDs are: \n");
    #define HP_ITEM(name, length) printf("  %2d=%s\n",HPID_##name, #name);
      HP_LIST
    #undef HP_ITEMS
    
    }
    

    是否有任何命名此类标识符的常规约定,以尽量减少冲突的可能性,并尽量减少它们可能产生的任何混淆?在上述场景中,标识符ZZQ\u xxx将与hp\u start[HPID\u xxx]相同,并且在某些上下文中可能有用,尽管它们的主要目的是构建数组,并在计算其他ZZQ值和hp\u TOTAL\u大小时充当占位符。然而,标识符ZZQX\u xxx是无用的;它们的唯一目的是在为后续项设置枚举值时充当占位符。有什么好办法来命名这些东西吗?

    顺便说一句,我为小微控制器开发的RAM是在一个更大的溢价比代码空间。代码是通过编译微软VC++来模拟的,但对于生产来说是使用交叉编译器在直C编译的;因此代码必须在C和C++中编译。

    对于类似的任务,还有其他预处理器技巧可以推荐吗?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Dummy00001    14 年前

    是否有任何命名此类标识符的常规约定,以尽量减少冲突的可能性,并尽量减少它们可能产生的任何混淆?

    HP_LIST

    为什么不把符号放在同一个下面呢 HP_ 前缀?例如前缀 HP__ZZQX_ ,以区分有用和无用的符号。

    注意:我参与过一个项目,其中一个共享库已经在使用(内部) zzqx_

    作为一个具体的东西,这里是你的源代码 hack around ## 要使用作为预处理器的前缀生成名称,请定义:


    /* the hack is needed to force the LIST_NAME to be expanded. 
       automatically adds underscores. yes, it's ugly */
    #define LIST_SYMBOL_1(n1,n2,n3) n1##_##n2##_##n3
    #define LIST_SYMBOL_0(n1,n2,n3) LIST_SYMBOL_1(n1,n2,n3)
    #define LIST_SYMBOL(pref,name)  LIST_SYMBOL_0(LIST_NAME,pref,name)
    
    /* give the name to the list. used by the LIST_SYMBOL(). */
    #define LIST_NAME   HP
    
    /* Give the names and their respective lengths */
    #define HP_LIST \
      HP_ITEM(FRED, 4) \
      HP_ITEM(GEORGE, 6) \
      HP_ITEM(HARRY, 5) \
      HP_ITEM(RON, 3) \
      HP_ITEM(HERMIONE, 8) \
      /* BLANK LINE REQUIRED TO ABSORB LAST BACKSLASH */
    
    #define HP_ITEM(name, length) HPID_##name,
    typedef enum { HP_LIST HP_ID_COUNT} HP_ID;
    #undef HP_ITEM
    
    #define HP_ITEM(name, length)   LIST_SYMBOL(ZZQ,name)}; \
        enum {LIST_SYMBOL(ZZQX,name)=LIST_SYMBOL(ZZQ,name)+(length)-1,
    enum { HP_LIST HP_TOTAL_SIZE};
    #undef HP_ITEM
    
    #define HP_ITEM(name, length) LIST_SYMBOL(ZZQ,name),
    const unsigned char hp_starts[] = { HP_LIST HP_TOTAL_SIZE};
    #undef HP_ITEM
    
    #include <stdio.h>
    
    void main(void)
    {
      int i;
      printf("ID count=%d Total size=%d\n",HP_ID_COUNT,HP_TOTAL_SIZE);
      for (i=0; i<HP_ID_COUNT ; i++) /* bring the < back, SO is smart enough */
        printf("  %2d=%3d/%3d\n", i, hp_starts[i], hp_starts[i+1]-hp_starts[i]);
      printf("IDs are: \n");
    #define HP_ITEM(name, length) printf("  %2d=%s\n",HPID_##name, #name);
      HP_LIST
    #undef HP_ITEMS
    }
    

    编辑1 . 我的首选方法是将数据放入适当的文本文件中,例如:

    FRED
    GEORGE
    HARRY
    RON
    HERMIONE
    

    那已经 巨大的

        2
  •  0
  •   Jens Gustedt    14 年前

    您可以检查boost项目中的预处理器宏。他们有聪明的预处理器计数器。一起 __LINE__ HP_ITEM 宏。