如何在C++;使用宏? 我在C++中创建了一个宏,声明一个变量并给它赋值。根据宏的使用方式,第二次出现的宏可以覆盖第一个变量的值。例如: #define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();

如何在C++;使用宏? 我在C++中创建了一个宏,声明一个变量并给它赋值。根据宏的使用方式,第二次出现的宏可以覆盖第一个变量的值。例如: #define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();,c++,variables,random,macros,naming,C++,Variables,Random,Macros,Naming,使用它的另一个动机是避免为变量选择特定的名称,以便它与使用宏的开发人员最终选择的名称相同 是否有一种在C++中的宏中生成随机变量名的方法? --编辑-- 我的意思是唯一的,但也是随机的,我可以在一个块中使用我的宏两次,在这种情况下,它将生成如下内容: int unique_variable_name; ... int unique_variable_name; 这种情况下,两个变量名必须是随机生成的。虽然我不认为它是可能的,但是你应该认真考虑把这个类做出来。 如果希望随机数组中的随机元素包含某

使用它的另一个动机是避免为变量选择特定的名称,以便它与使用宏的开发人员最终选择的名称相同

是否有一种在C++中的宏中生成随机变量名的方法? --编辑--

我的意思是唯一的,但也是随机的,我可以在一个块中使用我的宏两次,在这种情况下,它将生成如下内容:

int unique_variable_name;
...
int unique_variable_name;

这种情况下,两个变量名必须是随机生成的。

虽然我不认为它是可能的,但是你应该认真考虑把这个类做出来。

如果希望随机数组中的随机元素包含某个值,可以执行以下操作:

std::vector< std::vector<int> > m_vec;

有什么理由让它成为宏吗?随机变量名听起来很危险,如果它选择了代码中其他地方已经定义的东西怎么办?

将M4添加到构建流中?该宏语言具有一些有状态功能,可以成功地与CPP宏混合使用。这可能不是在C环境中生成唯一名称的标准方法,尽管我已经能够以这种方式成功地使用它

顺便说一句,根据你提出问题的方式,你可能不想要随机的。你想要独一无二的


您可以在宏展开中使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
来获得您想要的唯一性。。。这些元变量是在源文件上下文中定义的,因此请务必确保您得到了所需的内容(例如,同一行中有多个宏的危险)。

在预处理器中生成唯一名称是很困难的。您能得到的最接近的方法是按照建议将
\uuuuu文件\uuuuu
\uuuuuu行\uuuuuu
压缩到符号中。如果您真的需要生成唯一的全局符号名,那么我将按照他的建议,在构建系统中使用M4或Perl脚本

您可能不需要唯一的名称。如果宏可以施加一个新的作用域,那么可以使用相同的名称,因为它将简单地隐藏其他定义。我通常遵循在
do{…}while(0)
循环中包装宏的一般建议。这只适用于作为语句而不是表达式的宏。宏可以使用输出参数更新变量。例如:

#define CALC_TIME_SINCE(t0, OUT) do { \
     std::time_t _tNow = std::time(NULL); \
     (OUT) = _tNow - (t0); \
} while (0)
如果你遵循a,你通常是相当安全的:

  • 对宏中定义的符号使用前导下划线或类似的命名约定。这将防止与使用相同符号的参数相关的问题发生
  • 仅使用输入参数一次,并始终用括号将其括起来。这是使宏以表达式作为输入的唯一方法
  • 使用
    do{…}while(0)
    习惯用法确保宏仅用作语句,并避免其他文本替换问题

  • 您可以让宏用户给您一个名称,而不是让预处理器创建名称

    #define MY_MACRO(varname) int varname = getCurrentTime();
    

    使用
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


    对于没有任何评测工具的情况,我需要类似的东西,但我想计算一个特定代码块中有多少线程,以及每个线程在该代码块中花费的时间(滴答声),在这种情况下,每个代码块都需要一个唯一的静态变量,所有线程都可以访问,后来我需要将该变量引用到incr(我在实际代码中使用了一个日志API而不是printf,但这同样有效)。起初,我认为我很聪明,做了以下几件事:

    #define PROF_START { \
        static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
        clock_t start, end; \
        start = times(0); \
        (*ptc)++;
    
    // One level of macro indirection is required in order to resolve __COUNTER__,
    // and get varname1 instead of varname__COUNTER__.
    #define CONCAT(a, b) CONCAT_INNER(a, b)
    #define CONCAT_INNER(a, b) a ## b
    
    #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
    
    void main() {
      int UNIQUE_NAME(foo) = 123;  // int foo0 = 123;
      std::cout << foo0;           // prints "123"
    }
    
    但后来我意识到这很愚蠢,只要每个“静态”声明都是它自己的块,C编译器就会为您这么做:

    #include <stdio.h>
    #include <sys/times.h>
    
    #define PROF_START { \
        static int entry_count = 0; \
        clock_t start, end; \
        start = times(0); \
        entry_count++;
    
    
    #define PROF_END \
        end = times(0); \
        printf("[%s:%d] TIMER: %ld:%d\n" , __FUNCTION__, __LINE__, end-start, entry_count); \
        entry_count--; \
        }
    

    下面是一个简洁的宏定义,用于生成上面的单例模式

    #define SINGLETON_IMPLIMENTATION(CLASS_NAME) static CLASS_NAME *g##CLASS_NAME = nil; + (CLASS_NAME *)instance { @synchronized(self) { if (g##CLASS_NAME == nil) g##CLASS_NAME = [self new]; } return g##CLASS_NAME; }
    
    #define SINGLETON_DECLARATION(CLASS_NAME) + (CLASS_NAME *)instance;
    
    请尝试以下操作:

    #define PROF_START { \
        static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
        clock_t start, end; \
        start = times(0); \
        (*ptc)++;
    
    // One level of macro indirection is required in order to resolve __COUNTER__,
    // and get varname1 instead of varname__COUNTER__.
    #define CONCAT(a, b) CONCAT_INNER(a, b)
    #define CONCAT_INNER(a, b) a ## b
    
    #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
    
    void main() {
      int UNIQUE_NAME(foo) = 123;  // int foo0 = 123;
      std::cout << foo0;           // prints "123"
    }
    
    //需要一级宏间接寻址才能解析_计数器,
    //并获取varname1而不是varname\uuuuu计数器。
    #定义混凝土(a,b)内混凝土(a,b)
    #定义CONCAT_内部(a,b)a##b
    #定义唯一的\u名称(基)CONCAT(基,\u计数器)
    void main(){
    int-UNIQUE_-NAME(foo)=123;//int-foo0=123;
    
    std::cout使用前导下划线不是一个好主意,因为这样生成的名称可能与实现保留的名称冲突,并且在任何情况下都是保留的。事实上,宏的用户可能希望使用像_tNow这样的名称。我建议使用完整的宏名称作为宏使用的名称的前缀,在本例中为CALC_TIM还有一个计数器宏,每次调用它时都会生成新的整数,但它是非标准的。哇,现在注释格式也是如此!无论如何,它应该是计数器,前后都有两个下划线。这对我不起作用,因为我可能会在同一个文件中多次使用该宏并引用它在另一个宏中,“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu59449(int II,α=LIM=(Uu),II=(LL);III-α,LIM;++II)< /C> > -但是这是C++或C99(用于范围)。对于旧的C,类似的<代码> < /COD> >宏需要戴夫的技术。
    // One level of macro indirection is required in order to resolve __COUNTER__,
    // and get varname1 instead of varname__COUNTER__.
    #define CONCAT(a, b) CONCAT_INNER(a, b)
    #define CONCAT_INNER(a, b) a ## b
    
    #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
    
    void main() {
      int UNIQUE_NAME(foo) = 123;  // int foo0 = 123;
      std::cout << foo0;           // prints "123"
    }