0
votes

Recherche d'une macro ou d'un modèle de pré-processeur C / C ++ pour inverser un tableau de macro hexadécimal et générer un nombre hexadécimal

J'ai une question très précise. J'ai la macro suivante définie pour être utilisée dans le code plus tard.

x = 0x7766554433221100;
y = 0xFFEEDDCCBBAA9988;

Maintenant, je veux inverser l'ordre pendant la compilation et générer une valeur à incorporer directement dans l'exécutable pendant la compilation. Donc, fondamentalement, je veux le code suivant

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

afin qu'au moment de la compilation

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

Comment mon DO_IT et DO_TOO doivent ressembler à cela pour que cela fonctionne? J'ai vraiment du mal avec celui-ci et je n'arrive pas à trouver une solution qui fonctionne. Toute aide est grandement appréciée.


7 commentaires

Votre tableau a-t-il toujours les mêmes éléments numériques? Pouvez-vous modifier votre macro MY_ARRAY afin qu'elle n'inclue pas les accolades? Et pourquoi voulez-vous le faire avec une macro et non avec une fonction?


Il contient en fait 16 éléments (je mettrai à jour la question). Numéro hexadécimal de 64 bits. Il contient les accolades car il sera nécessaire plus tard dans le code hérité sur lequel je travaille.


#define reverse (a, b) b, a ? DO_IT est impossible - il est impossible de supprimer { } au niveau du préprocesseur. Pouvez-vous supprimer le { } ? Qu'est-il arrivé également à 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF ?


Mais cela ne rentrera pas dans un int 64 bits; vous auriez besoin de 128 bits. Si vous pouvez définir MY_ARRAY en deux étapes - l'une sans accolades, l'autre avec accolades - vous pouvez alors créer le nombre avec bt-shifting: #define (A0, A1, .. .) (((A0) << 0) | ((A1) << 8) | ...)


C et C ++ sont des langages différents, et C ++ peut effectuer des calculs de compilation plus complexes - non basés sur des macros - que C. Choisissez votre langage.


Ok, c'est plus compliqué que je ne le pensais. C'est en fait un tableau de 16 octets qui doit être stocké dans 2 variables. Dieu aide moi. Nous utilisons un compilateur C ++ pour que je puisse utiliser les fonctionnalités C ++ (bien qu'elles ne soient pas encore utilisées car il s'agit de code C hérité).


La virgule 0x77 \ 0x88 est manquante, par intention ou par faute de frappe?


3 Réponses :


2
votes

Si vous supprimez { } , vous pouvez simplement:

#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);

mettre à jour:

#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)


2 commentaires

Ok, ouais. En fait, je peux simplement supprimer les accolades et les ajouter via une autre macro pour le code hérité et utiliser essentiellement MY_ARRAY_RAW comme ceci, puis faire en sorte qu'un MY_ARRAY soit un {MY_ARRAY_RAW}. Je vais essayer ça. Merci!


Merci!!! Cela fonctionnait à l'aide de macros. J'ai dû faire quelques changements car j'utilise MSVC et n'adhère pas à la norme lors de l'extension des arguments. J'ai trouvé une solution cependant: stackoverflow.com/questions/35210637 /…



0
votes

Veuillez jeter un œil à la solution de la bibliothèque Boost: https://www.boost.org/ doc / libs / 1_68_0 / libs / preprocessor / doc / ref / array_reverse.html

BOOST_PP_ARRAY_REVERSE est ce dont vous avez besoin.


1 commentaires

Merci pour la suggestion, mais je préfère ne pas ajouter la bibliothèque boost si je peux l'aider.



2
votes

Il ne semble pas y avoir de raison d'utiliser des macros ici, vous avez juste besoin d'une évaluation au moment de la compilation:

#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);
}

Ceci est indépendant et standard C. Il peut être facilement réécrit pour être utilisé Types 64 bits qui est probablement (?) Ce que vous voulez réellement?


0 commentaires