【问题标题】:Can you make an incrementing compiler constant?你能做一个递增的编译器常量吗?
【发布时间】:2010-03-31 22:44:33
【问题描述】:

虽然听起来很荒谬.....

我想要一个常量,每次使用它都会增加 1

int x;
int y;
x = INCREMENTING_CONSTANT;
y = INCREMENTING_CONSTANT;

其中 x == 1;和 y == 2

注意我不想要 y = INCREMENTING_CONSTANT+1 类型的解决方案。

基本上我想将其用作编译时唯一 ID(通常不会在示例代码中使用,而是在另一个宏中使用)

【问题讨论】:

  • 由于变量是基于编译器的,我们需要知道你说的是哪个编译器。
  • 交叉编译器...理想情况下,它将用于至少 3 个编译器。
  • 这实际上重复了stackoverflow.com/questions/2076757/incremented-define,但解决方案适用于 C++,但会看看我是否可以将相同的技术用于 C
  • @LưuVĩnhPhúc 这是 C++ 的,如果你检查这个答案,有一个解决方案可以在 C++ 中做他们想做的事情

标签: c


【解决方案1】:

如果您只需要一些唯一 ID ish,您可以使用 __LINE__ 预处理器符号吗?这不是您要的,但它可能对您有用。

【讨论】:

  • 同意,我总是使用 'LINE' 来处理我看到使用 'COUNTER' 的相同类型的东西。
  • LINE 是我不想使用的东西
【解决方案2】:

这不是标准的,但一些编译器支持 __COUNTER__ 宏。见Has anyone ever had a use for the __COUNTER__ pre-processor macro?

【讨论】:

    【解决方案3】:

    您可以使用 Boost.Preprocessor(与 C 一起使用)和 BOOST_PP_COUNTER 将一些东西放在一起

    docs 页面上给出的示例:

    #include <boost/preprocessor/slot/counter.hpp>   
    BOOST_PP_COUNTER // 0
    
    #include BOOST_PP_UPDATE_COUNTER()   
    BOOST_PP_COUNTER // 1
    
    #include BOOST_PP_UPDATE_COUNTER()  
    BOOST_PP_COUNTER // 2
    
    #include BOOST_PP_UPDATE_COUNTER()
    BOOST_PP_COUNTER // 3
    

    翻译成你想要的

    #include <boost/preprocessor/slot/counter.hpp> 
    
    int x = BOOST_PP_COUNTER; // 0
    
    #include BOOST_PP_UPDATE_COUNTER()   
    int y = BOOST_PP_COUNTER;// 1
    
    #include BOOST_PP_UPDATE_COUNTER()  
    int z = BOOST_PP_COUNTER; // 2
    

    您也可以使用插槽(比上述解决方案更灵活,但需要更多代码):

    #include <boost/preprocessor/slot/slot.hpp>
    
    #define BOOST_PP_VALUE 0 //ensure 0 to start
    #include BOOST_PP_ASSIGN_SLOT(1) 
    int a = BOOST_PP_SLOT(1); //0
    
    #define BOOST_PP_VALUE 1 + BOOST_PP_SLOT(1)
    #include BOOST_PP_ASSIGN_SLOT(1) 
    int b = BOOST_PP_SLOT(1); //1
    

    【讨论】:

    • 奇怪的构造#include BOOST_PP_UPDATE_COUNTER() - 你真的必须在每次增加计数器时都包含它吗?老实说,我不认为这是一种非常方便的方法,因此不要使用此解决方案。
    【解决方案4】:

    在我的例子中,我希望每个子系统都有一个系统范围的唯一密钥,但子系统的选择将取决于使用系统的人。这些值必须是 8 位值,因为它是针对嵌入式系统的。

    这是我刚刚想到的:

    #define LAST_KEY -1
    
    // SUB1_KEY definition
    enum {
      SUB1_KEY_ORIGIN = LAST_KEY,
      SUB1_KEY,
    };
    #undef LAST_KEY
    #define LAST_KEY SUB1_KEY
    
    // SUB2_KEY definition
    enum {
      SUB2_KEY_ORIGIN = LAST_KEY,
      SUB2_KEY,
    };
    #undef LAST_KEY
    #define LAST_KEY SUB2_KEY
    
    // SUB3_KEY definition
    enum {
      SUB3_KEY_ORIGIN = LAST_KEY,
      SUB3_KEY,
    };
    #undef LAST_KEY
    #define LAST_KEY SUB3_KEY
    
    // ....
    

    挑战将是确保每次都以相同的顺序编译引入每个块的包含链。

    【讨论】:

      【解决方案5】:

      我经常希望有编译时变量。然而,最简单的做法就是为每个单独定义常量。

      如果您使用的是 C 而不是 C++,则可以通过在某个全局状态类中使用 functionoid 或类似的解决方案来解决我上面的线程问题的答案。

      您也可以尝试使用 xmacro。创建一个新文件,我们称之为 xmacro.h

      INCREMENTING_CONSTANT;
      #define INCREMENTING_CONSTANT INCREMENTING_CONSTANT + 1
      

      然后,在标准标题中,

      #define INCREMENTING_CONSTANT 0
      #define USE_INCREMENTING_CONSTANT #include "xmacro.h"
      
      const int x = USE_INCREMENTING_CONSTANT
      

      我还没有对此进行测试,但是 xmacros 具有一些常规宏无法使用的强大功能,例如 defs/undefs,而且我的直觉认为它应该可以工作。预处理器功能强大,但相当笨拙,因此可能会失败。

      【讨论】:

      • 这不起作用 - 预处理器看不到宏扩展产生的指令。
      • 我独立地找到了这个解决方案,尝试了它,但它不起作用......这就是我在这里的原因:-)
      【解决方案6】:

      您希望xy 本身成为常量吗?如果是这样,最简单和最干净的做法可能是使用匿名枚举:

      enum {
          x = 1,
          y
          /* Add new ones here. */
      };
      

      这意味着您只需向该列表添加一个新名称,它将被赋予下一个整数值。这是一个有用的技巧,您不必关心值是什么(在运行时之外),只要它们不同即可。例如,在为 GUI 中的控件分配标识符时,您经常会看到:

      enum {
          button1_id = FIRST_USER_ID,
          button2_id,
          combo_id,
          ...
      }
      

      一些 GUI 框架提供了一个 GetUserId() 函数,该函数将生成一个新的(使用内部静态变量);但我认为这发生在运行时。接连看到这么多调用也有点乏味。

      button1_id = GetUserId();
      button2_id = GetUserId();
      combo_id = GetUserId();
      ...
      

      【讨论】:

      • 遗憾的是,我不能使用枚举的东西,它完全不知道可能有多少项。
      • 我不知道为什么这是个问题。为什么向枚举中添加新项比(例如)添加另一行代码以在其他地方将其初始化为某个常量更难?
      • 因为宏可能出现在代码中的任何位置。很可能它会在一个函数的主体中......另一个宏将在另一个函数的主体中等等,在许多不同的函数中都会有任意数量的宏引用。每次出现宏时,我希望它增加 1
      【解决方案7】:

      那么,它不是恒定的,是吗? ;)

      你可以用一个函数来做到这一点:

      int id() {
        static int i = 0;
        return ++i;
      }
      
      x = id();
      y = id();
      

      如图所示,这不是线程安全的。为此,您需要使用互斥锁来保护它,或者使用编译器/平台特定的原子增量器。

      【讨论】:

      • 好吧,编译时间常数 :) 这是你的答案完全失败的地方! :) 因此我的问题是,如何使递增的编译时间保持不变!很像____LINE____会根据您所在的代码行而变化:)
      • 我认为这不是他想要的。这将在每次调用函数时在运行时生成一个新值。我认为他希望在编译时计算一次该值,然后每次运行该行时使用相同的值。
      【解决方案8】:

      “递增常数”是矛盾的。您不能在编译时执行此操作。

      【讨论】:

      • 看起来像一个,但“常量”部分是指在编译时保持不变而不是符号。
      • 其实是很多常数值,一个比一个大
      【解决方案9】:

      这是一个丑陋的实现方式。

      static int _counter=0;
      #define INCREMENTING_CONSTANT (_counter++)
      

      【讨论】:

        猜你喜欢
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-20
        • 2019-02-13
        • 2011-08-13
        • 1970-01-01
        • 2017-06-09
        相关资源
        最近更新 更多