Как я могу генерировать уникальные значения в препроцессоре C?

Обратите внимание, что значение, которое Вы форматируете, должно быть числовым. Не похоже, что это возьмет строковое представление числа, и формат с запятыми.

17
задан Brian Tompsett - 汤莱恩 11 February 2016 в 16:46
поделиться

6 ответов

As others noted, __COUNTER__ is the easy but nonstandard way of doing this.

If you need extra portability, or for other cool preprocessor tricks, the Boost Preprocessor library (which works for C as well as C++) will work. For example, the following header file will output a unique label wherever it's included.

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/slot/slot.hpp>

#if !defined(UNIQUE_LABEL)
#define UNIQUE_LABEL
#define BOOST_PP_VALUE 1
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#else
#define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1))
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#endif


BOOST_PP_CAT(my_cool_label_, BOOST_PP_SLOT(1)):

Sample:

int main(int argc, char *argv[]) {
    #include "unique_label.h"
    printf("%x\n", 1234);
    #include "unique_label.h"
    printf("%x\n", 1234);
    #include "unique_label.h"
    return 0;
}

preprocesses to

int main(int argc, char *argv[]) {
    my_cool_label_1:
    printf("%x\n", 1234);
    my_cool_label_2:
    printf("%x\n", 1234);
    my_cool_label_3:
    return 0;
}
15
ответ дан 30 November 2019 в 10:27
поделиться

Если вы используете GCC или MSVC, есть __ COUNTER __ .

Кроме этого, вы можете сделать что-нибудь достойное рвоты, например:

#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
18
ответ дан 30 November 2019 в 10:27
поделиться

Я не могу придумать способ их автоматического создания, но вы можете передать параметр в MAKE_LABEL:

#define MAKE_LABEL(n) my_cool_label_##n:

Тогда ...

MAKE_FUNNY_JUMPING_LOOP(
  MAKE_LABEL(0);
  MAKE_LABEL(1);
)
7
ответ дан 30 November 2019 в 10:27
поделиться

Это невозможно со стандартным препроцессором, хотя вы можете подделать это, поместив параметры в MAKE_LABEL или MAKE_FUNNY_JUMPING_LOOP и используя вставку токена в создать этикетку.

Ничто не мешает вам создать собственный сценарий предварительной обработки, который выполняет автоматическое приращение за вас. Однако в этом случае это не будет стандартный файл C / C ++.

Список доступных команд: http: //www.cppreference. com / wiki / preprocessor / start

-2
ответ дан 30 November 2019 в 10:27
поделиться

Вы не можете использовать только один список, потому что вы не получите представления о глубине дерева. Таким образом, вам определенно понадобится два или более списка.

Вот моя попытка решения:

Используйте предварительный обход данных, чтобы узнать порядок данных. Это имеет смысл, потому что вы знаете, что первый узел находится наверху, и вы знаете, что данные, расположенные слева от обхода, принадлежат левой части дерева и т. Д.

Обход вашего почтового заказа может определять глубину дерева. Например, предположим, что у меня есть такая структура:

      1
  2   5   6
 3 4  7

Where 2 is the parent of 3 and 4, and 5 is the parent of 7.

Preorder: 1 2 3 4 5 7 6
Postorder: 3 4 2 7 5 6 1

Мы знаем, что начинаем с 1, потому что это первый узел в обходе предварительного заказа. Затем мы смотрим на следующее число, 2. В почтовом порядке, поскольку число 2 идет ПЕРЕД узлом 1, мы знаем, что 2 должен быть дочерним по отношению к 1. Затем мы смотрим на 3. 3 идет перед 2, и, следовательно, 3 является дочерним элементом 2. 4 находится перед 2, но после 3, поэтому мы знаем, что 4 является дочерним элементом 2, но НЕ является дочерним элементом 3. И т. д.

Теперь это может не сработать, если узлы не уникальны, но в по крайней мере, это начало решения.

Изменить: Неясно, как ваш макрос «MAKE_FUNNY_JUMPING_LOOP» ссылается на эти метки. Вы можете объяснить?

0
ответ дан 30 November 2019 в 10:27
поделиться

Я использую это:

#define MERGE_(a,b)  a##b
#define LABEL_(a) MERGE_(unique_name_, a)
#define UNIQUE_NAME LABEL_(__LINE__)

int main()
{
    int UNIQUE_NAME = 1;
    return 0;
}

... и получаю следующее:

int main()
{
    int unique_name_8 = 1;
    return 0;
}
17
ответ дан 30 November 2019 в 10:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: