Ищите макрос или шаблон препроцессора C / C ++ для обращения к массиву шестнадцатеричных макросов и генерации шестнадцатеричного числа - PullRequest
0 голосов
/ 17 апреля 2020

У меня очень конкретный c вопрос. У меня есть следующий макрос, который будет использоваться в коде позже.

#define MY_ARRAY { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 \
                   0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}

Теперь я хочу изменить порядок во время компиляции и сгенерировать значение, которое будет непосредственно встроено в исполняемый файл во время компиляции. В общем, я хочу следующий код

long x = DO_IT(MY_ARRAY);
long y = DO_TOO(MY_ARRAY);

, чтобы во время компиляции

x = 0x7766554433221100;
y = 0xFFEEDDCCBBAA9988;

Как бы мои DO_IT и DO_TOO имели чтобы это выглядело? Я действительно борюсь с этим и не могу найти рабочее решение. Любая помощь очень ценится.

Ответы [ 3 ]

2 голосов
/ 17 апреля 2020

Не похоже, что здесь есть какая-либо причина использовать макросы, вам просто нужна оценка во время компиляции:

#include <stdio.h>
#include <stdint.h>

#define MY_INIT_LIST { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, \
                       0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, }
#define MY_ARRAY (const uint32_t[]) MY_INIT_LIST

int main (void) 
{
  for(size_t i=0; i<16; i++)
    printf("%X ", MY_ARRAY[i]);

  const uint32_t u32 = MY_ARRAY[3] << 24 |
                       MY_ARRAY[2] << 16 |
                       MY_ARRAY[1] <<  8 |
                       MY_ARRAY[0] <<  0 ;
  printf("\n%X\n", u32);
}

Это независимый от байтов и стандартный C. Он может быть легко переписан для использования 64-битных типов, что, вероятно, (?) То, что вы на самом деле хотите?

2 голосов
/ 17 апреля 2020

Если вы удалите { }, вы можете просто:

#define MY_ARRAY  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
#define DO_IT_2(_0,_1,_2,_3,_4,_5,_6,_7)  (\
     (unsigned long long)(_7) << (7 * 8) | \
     (unsigned long long)(_6) << (6 * 8) | \
     etc...            \
     (unsigned long long)(_0) << (0 * 8))
#define DO_IT(x)  DO_IT_2(x)

обновить:

#define MY_ARRAY2 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
               0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
#define REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7)  (\
     (unsigned long long)(_7) << (7 * 8) | \
     (unsigned long long)(_6) << (6 * 8) | \
     etc...            \
     (unsigned long long)(_0) << (0 * 8))
#define DO_IT_2(_0,_1,_2,_3,_4,_5,_6,_7,...)  \
        REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7)
#define DO_IT(x) DO_IT_2(x)
#define DO_TOO_2(a0,a1,a2,a3,a4,a5,a6,a7,_0,_1,_2,_3,_4,_5,_6,_7)  \
        REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7)
#define DO_TOO(x) DO_TOO_2(x)

DO_IT(MY_ARRAY2)
DO_TOO(MY_ARRAY2)

, чтобы я мог использовать функции C ++

В C ++ это действительно простая contexpr функция с initializer_list:

#include <initializer_list>
#define MY_ARRAY  {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
constexpr unsigned long long DO_IT(const std::initializer_list<int>& l) {
    unsigned long long r = 0;
    for (auto&& i : l) {
        r >>= 8;
        r |= (unsigned long long)i << (7 * 8);
    }
    return r;
}
constexpr long a = DO_IT(MY_ARRAY);
0 голосов
/ 17 апреля 2020

Пожалуйста, взгляните на решение библиотеки Boost: https://www.boost.org/doc/libs/1_68_0/libs/preprocessor/doc/ref/array_reverse.html

BOOST_PP_ARRAY_REVERSE - это то, что вам нужно.

...