Affichage de la valeur de constantes a la compilation [Résolu]

Signaler
Messages postés
576
Date d'inscription
jeudi 28 novembre 2002
Statut
Membre
Dernière intervention
5 juin 2021
-
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
-
Bonjour,
Pour la mise au point de macros ,on a souvent besoin d'afficher des résultats intermédiaires
a la compilation.
exemple :
#define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) |     \
                  (((DWORD)(ch4) & 0xFF00) << 8) |    \
                  (((DWORD)(ch4) & 0xFF0000) >> 8) |  \
                  (((DWORD)(ch4) & 0xFF000000) >> 24))

en pseudo code:
afficher_valeur (FCC(555))                // affichage dans fenêtre compilation

8 réponses

Messages postés
576
Date d'inscription
jeudi 28 novembre 2002
Statut
Membre
Dernière intervention
5 juin 2021
2
Vu l'absence de réponse,cela ne semble pas possible.


--
Messages postés
16006
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
5 juin 2021
549
Bonjour, ne tire pas de conclusion hâtive.
L'absence de réponse est d'abord due au peu de fréquentation du site, encore moindre au moi d'aout.
Messages postés
576
Date d'inscription
jeudi 28 novembre 2002
Statut
Membre
Dernière intervention
5 juin 2021
2
J'ai trouvé "#pragma message" semblant convnir.
#include <windows.h>
#include <iostream>

#define STRING2(x) #x
#define STRING(x) STRING2(x)


#define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) |     \
                  (((DWORD)(ch4) & 0xFF00) << 8) |    \
                  (((DWORD)(ch4) & 0xFF0000) >> 8) |  \
                  (((DWORD)(ch4) & 0xFF000000) >> 24));

int main()
{

    const int rien = FCC(555);
     #pragma message (__FILE__ "[" STRING(__LINE__) "]: test") 
    #pragma message(STRING(FCC(555)))
    #pragma message(STRING(rien))


affichage:
essai.cpp[22]: test
((((DWORD)(555) & 0xFF) << 24) | (((DWORD)(555) & 0xFF00) << 8) | (((DWORD)(555) & 0xFF0000) >> 8) | (((DWORD)(555) & 0xFF000000) >> 24));
rien
rien devrait apparaitre comme un chiffre ,comment faire ?
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Bonjour !

Tu ne peux pas afficher la valeur d'une variable calculée à l'exécution, lors de la compilation. Soit tu affiches la valeur du résultat de FCC(), soit tu mets ce résultat en tant qu'alias dans un define.

Exemple:
#include <iostream>

// DWORD not exist on Unix, let's alias it :). Remove this line on Windows.
#define DWORD unsigned long int

#define STRING2(x) #x
#define STRING(x) STRING2(x)

#define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) |       \
                  (((DWORD)(ch4) & 0xFF00) << 8) |      \
                  (((DWORD)(ch4) & 0xFF0000) >> 8) |    \
                  (((DWORD)(ch4) & 0xFF000000) >> 24));

#define RIEN FCC(555)

int main()
{
  const int rien = RIEN;

#pragma message (__FILE__ "[" STRING(__LINE__) "]: test")
#pragma message(STRING(FCC(555)))
#pragma message(STRING(RIEN))
#pragma message(STRING(rien))

  std::cout << rien << std::endl;
  return 0;
}


Si tu veux le résultat, et non l'expression, ce n'est pas possible sans exécuter le code tout simplement. Le pré-processeur manipule du texte, il n'interprète, ni ne calcul rien.
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Bon, j'ai trouvé une solution "sale", et qui ne fonctionne pas partout.
Ça consiste à détourner un warning particulier, pour qu'il affiche le résultat d'un template.
Ça fonctionne sous clang et g++, je ne sais pas si ça fonctionnera avec Visual Studio :(.

Voici le code:
#include <iostream>

#define DWORD unsigned long int

template <DWORD N>
struct MSG
{
  MSG()
  {
    int i;
    int d = i; // Provoque un warning uninitialized volontairement.
  }
};

#define FCC(ch4) ((((DWORD)(ch4)&0xFF) << 24) |    \
                  (((DWORD)(ch4)&0xFF00) << 8) |   \
                  (((DWORD)(ch4)&0xFF0000) >> 8) | \
                  (((DWORD)(ch4)&0xFF000000) >> 24))

#define MESSAGE(expr) MSG<expr>()

int main()
{
  MESSAGE(4 + 5);
  MESSAGE(FCC(555));

  return 0;
}


Il faut que la compilation soit lancée avec des options particulières:
g++ masm.cc -std=c++11 -Wuninitialized


Voici le résultat chez moi (inesthétique, mais fonctionnel):
masm.cc:11:13: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
int d = i;
^
masm.cc:24:3: note: in instantiation of member function 'MSG<9>::MSG' requested here
MESSAGE(4 + 5);
^
masm.cc:20:23: note: expanded from macro 'MESSAGE'
#define MESSAGE(expr) MSG<expr>()
^
masm.cc:10:10: note: initialize the variable 'i' to silence this warning
int i;
^
= 0
masm.cc:11:13: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
int d = i;
^
masm.cc:25:3: note: in instantiation of member function 'MSG<721551360>::MSG' requested here
MESSAGE(FCC(555));
^
masm.cc:20:23: note: expanded from macro 'MESSAGE'
#define MESSAGE(expr) MSG<expr>()
^
masm.cc:10:10: note: initialize the variable 'i' to silence this warning
int i;
^
= 0
2 warnings generated.


Ça reste très bancale. Pas sur que ce soit possible "proprement".
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
J'ai une solution un petit peu moins "moche", et qui pourrait fonctionner sur un compilateur qui supporte le "static_assert". Le défaut par contre, c'est que c'est une erreur et non un warning, et donc la compilation s'arrête :(.

Voici le code:
#include <iostream>

#define DWORD unsigned long int

#define FCC(ch4) ((((DWORD)(ch4)&0xFF) << 24) |    \
                  (((DWORD)(ch4)&0xFF00) << 8) |   \
                  (((DWORD)(ch4)&0xFF0000) >> 8) | \
                  (((DWORD)(ch4)&0xFF000000) >> 24))

template <DWORD N>
struct MSG
{
  static const bool val = false;
};

#define MESSAGE(expr) static_assert(MSG<expr>::val, #expr)

int main()
{
  MESSAGE(4 + 5);
  MESSAGE(FCC(555));
}


Chez moi, j'ai ceci:
masm.cc:20:3: error: static_assert failed due to requirement 'MSG<7>::val' "3 + 4"
MESSAGE(3 + 4);
^~~~~~~~~~~~~~
masm.cc:16:23: note: expanded from macro 'MESSAGE'
#define MESSAGE(expr) static_assert(MSG<expr>::val, #expr)
^ ~~~~~~~~~~~~~~
masm.cc:21:3: error: static_assert failed due to requirement 'MSG<721551360>::val' "FCC(555)"
MESSAGE(FCC(555));
^~~~~~~~~~~~~~~~~
masm.cc:16:23: note: expanded from macro 'MESSAGE'
#define MESSAGE(expr) static_assert(MSG<expr>::val, #expr)
^ ~~~~~~~~~~~~~~
2 errors generated.
Messages postés
576
Date d'inscription
jeudi 28 novembre 2002
Statut
Membre
Dernière intervention
5 juin 2021
2
Bonjour,
Merci pour les efforts.
Il y a quelque chose que je ne comprends pas trop.

#define STRING2(x) #x
#define STRING(x) STRING2(x)

Vu de loin ,ça ressemble a quelque chose de magique ,d'autant plus que j'ai vu les mêmes définitions avec un autre nom et une même utilisation.
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Les macro C ne sont pas vraiment récursives. Elles "expandent" ce qu'elles trouvent. Or, si tu veux forcer une sous macro à être expand, il faut repasser dessus.
Quelques (succintes) explications ici:
https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms#recursion

Un exemple:
#include <iostream>

#define _STR(x) #x
#define STR(x) _STR(x)
#define ADD(a, b) a + b

int main()
{
  std::cout << _STR(ADD(3, 4)) << std::endl; // ADD(3, 4)
  std::cout << STR(ADD(3, 4)) << std::endl;  // 3 + 4
}


Si on applique "#" sur ADD(3, 4), il nous affichera, littéralement "ADD(3, 4)".
Il faut lui dire d'interpréter la macro ADD, et pour ça on le fait passer par une étape "inutile" juste pour forcer le préprocesseur à interpréter ce qui est contenu.