0
votes

Entraînement des macros en-tête en pleine expansion pour obtenir leurs valeurs numériques pour une utilisation externe

J'ai un fichier d'en-tête compliqué avec de nombreuses dépendances sur d'autres macros définies précédemment qui disposent de la carte mémoire d'un système intégré. Par exemple: xxx pré>

Pour de nombreuses raisons, j'ai besoin du résultat de Secure_ram_base code> en dehors du programme compilé. Ainsi, ma pensée était d'utiliser le prétraiteur C pour développer ces macros et awk code> le résultat au besoin. Cependant, l'expansion macro avec CPP -DD code> était exactement comme indiqué ci-dessus (moins d'espace blanc supplémentaire). p>

J'attendais quelque chose comme ceci: p> xxx pré>

mais il semble (au moins aussi loin que j'éteigne la page man) que cette expansion ne soit que Accessible lorsque les macros sont en réalité utilisés dans le code em>. Même toujours, l'utilisation de code suivante: p> xxx pré>

se développe à: p>

printf("Base: 0x%x\n", ((0x40000000) + (0x10000000) - (0x00200000)));


11 commentaires

Le préprocesseur ne calcule pas. Ce que vous avez observé est le comportement normal.


@Yunnosch je n'étais pas au courant. J'ai supposé que cela a suivi les calculs jusqu'au résultat final. Sinon, le compilateur doit revenir plus tard et le faire quand même.


En fait, la production pré-traitée ne doit pas contenir du tout des définitions de macro. Cela ne devrait contenir que leurs substitutions. Je dirais, à vos fins, le mieux que vous puissiez faire est de définir des variables avec des valeurs égales à ces macros et que Grep pour ces variables.


J'essaie de trouver la signification de vous -dd , car j'utiliserais réellement -e . Cela ne vous aidera pas non plus, car mon premier commentaire se tient.


@Yunnosch à partir du manuel du CPP: -DD comme -DM, sauf à deux égards: il n'inclut pas les macros prédéfinies et génère les directives #define et le résultat du prétraitement . Avec mon hypothèse que le CPP effectué par les calculs finaux, le maintien de la partie #define de la définition macro semblait être un moyen d'obtenir la valeur étendue. L'option n'est pas définie dans le manuel, mais elle est mentionnée. J'ai vu les autres en utilisant -e à cette fin.


@Yunnosch: le pré-processeur ne calcule pas à moins d'avoir besoin de le faire. #if secure_ram_base nécessite un calcul du préprocesseur. Mais lors de l'expansion d'une macro, le préprocesseur ne calcule pas - principalement parce qu'il n'a pas le contexte complet de l'expression pour le guider.


@Jonathanleffler Bon point. Merci. Il aurait donc dû être "Le préprocesseur ne calcule pas pour développer des macros ."


@Yunnosch - 'pour' ou 'Alors que' EXTENDIER MACROS - Oui.


Pouvez-vous nous parler de "en dehors du programme compilé" s'il vous plaît? C'est peut-être un autre cas du problème X-Y.


@Thebusybee Je ne sais pas ce que tu veux dire. Mais je compose un micrologiciel de plusieurs étapes qui est composé de trois fichiers binaires tous liés à trois adresses. J'ai partitionné la RAM disponible en trois régions. Au moment de la liaison, je veux être capable de calculer les adresses finales et de les transmettre à la liaison si nécessaire. Pour obtenir ces adresses, j'ai besoin des expansions du fichier d'en-tête qui établit le système de partitionnement. Les adresses sont également utilisées " à l'intérieur " du programme compilé, mais j'en ai aussi besoin d'eux " à l'extérieur " à cet effet.


Si vous avez l'intention de traiter la sortie à l'aide de Awk de toute façon, pourquoi ne l'utilisez-vous pas également pour calculer également les opérations arithmétiques?


3 Réponses :


0
votes

existe-t-il un moyen de produire un résultat d'expansion «entièrement calculé» à l'aide du préprocesseur C? P>

Non, ce n'est pas possible. Le préprocesseur C ne calcule que quelque chose dans les expressions après #if code> et #elif code>. En termes simples, le prétraiteur C fonctionne dans la plupart des cas en tant que substitution de chaîne. Il voit secure_ram_base code> il ne remplace-t-il pas pour (RAM_BASE + RAM_SIZE - Secury_RAM_SIZE) CODE> et le remplaçoit pour ((0x10000000) - (0x00200000) - (0x00200000)) / code>. Aucun calcul n'est effectué sauf dans #if code> et #endif code>, seulement la substitution de chaîne. P>

qui dit ..., évidemment, vous pouvez: P >

#define RAM_BASE           (0x40000000)
#define RAM_SIZE           (0x10000000) 
#define SECURE_RAM_SIZE    (0x00200000)
#define SECURE_RAM_BASE_CALC    (RAM_BASE + RAM_SIZE - SECURE_RAM_SIZE)

#if SECURE_RAM_BASE_CALC == 1
#define SECURE_RAM_BASE 1
#elif SECURE_RAM_BASE_CALC == 2
#define SECURE_RAM_BASE 2
#elif SECURE_RAM_BASE_CALC == 3
#define SECURE_RAM_BASE 3
// ...
// ca. about 0x4fe00000 * 2 = 2680160256 =~ 2 bilion! more lines...
// ...
#elif SECURE_RAM_BASE_CALC == 0x4fe00000
#define SECURE_RAM_BASE 0x4fe00000
#endif


2 commentaires

Techniquement, le préprocesseur fonctionne sur un flux de jetons, pas sur une ficelle.


"Mais ceci est de bien excuser" ... ...



0
votes
  1. Vous pouvez écrire un programme C simple qui inclut cet en-tête (s) et imprime le résultat.

  2. Vous pouvez même la laisser imprimer la ligne de commande de liaison.

  3. Enfin, vous pouvez laisser ce petit programme exécuter la ou les commandes.

    C'est maintenant à vous avec quelle étape vous serez le plus heureux.


3 commentaires

J'ai fait 1 mais c'est certainement non idéal. J'espérais une belle solution CPP + Grep / AWK dans le maquillage, mais une autre étape n'est pas terrible.


Eh bien, comme vous semblez compiler certains programmes C, un autre ne sera pas blessé, à coup sûr. ;-) Et il n'y aura pas de dépendance sur d'autres outils tels que Grep et (g) awk.


Un problème avec la rédaction d'un programme comprenant l'en-tête et les impressions Les résultats sont qu'il doit souvent être exécuté sur une plate-forme hôte / Build plutôt que sur la plate-forme cible. Dans ce cas, c'est une implémentation C différente et peut avoir une arithmétique différente due à différentes largeurs de types entier et d'autres problèmes. Une solution de contournement pour obtenir les résultats corrects consiste à utiliser l'extension ASM ASM de GCC pour générer un faux code "assembly" qui inclut les valeurs comme opérande immédiate (% i si je me souviens bien. ), puis compilez avec -s pour générer un assemblage et extraire les valeurs de celui-ci.



3
votes
Y a-t-il un moyen de produire un résultat d'expansion «entièrement calculé» à l'aide du préprocesseur C?

Pourquoi, oui, il y a. (Incidemment, le préprocesseur de boost résout un problème similaire à l'aide de son concept de Slots ; mais la solution ici est plus adaptée à ce cas d'utilisation et les sorties hexagonales). Commentaires sur votre question pose déjà les règles de la terre ... C Préprocesseur Macro expansion ne peut pas évaluer les expressions. Mais les directives conditionnelles du préprocesseur C peuvent. Les directives conditionnelles ne sont pas Réduisez les expressions em>, mais avec un peu de travail, vous pouvez obtenir le RPC pour coaxer les résultats. Étant donné que votre objectif est de simplement obtenir des résultats, vous n'êtes pas réellement limité par l'évaluation macro. P>

approche de haut niveau fort> p>

Compte tenu de ces contraintes, vous voulez Un fichier consacré à l'évaluation et à l'impression d'une expression (disons que c'est appelé print_expression.h code>). L'évaluation doit être effectuée par une directive inclure; I.e., #include "print_expression.h" code>; De cette façon, nous pouvons utiliser l'outil de CPP capable d'évaluer les expressions (VIZ, des directives conditionnelles) pour le faire. Nous pouvons simplement avoir ce fichier évaluer l'expression expression code>; Vous pouvez #define code> ceci avant l'inclusion. Puisque vous allez réutiliser cela pour plusieurs macros qui développent les expressions, nous voudrons peut-être préférer le résultat d'évaluation avec expression_label code>, que vous pouvez définir comme quelque chose. Comme il s'agit d'un programme de préprocesseur plutôt qu'à un en-tête «normal», il peut être utile de manière utile après elle-même et sauter des gardes d'inclusion afin que vous puissiez la réutiliser immédiatement. P>

Conduite de la solution forte>

Donc, pour maintenant ignorer les détails et supposons que cela fonctionne simplement ... Pour générer quelque chose de ressemblant aux sorties que vous souhaitez sur votre en-tête d'échantillon, vous incluez l'en-tête, puis de pomper cet utilitaire comme suit. : P>

#define HEXRESULT(A,B,C,D,E,F,G,H) HEXRESULTI(A,B,C,D,E,F,G,H)
#define HEXRESULTI(A,B,C,D,E,F,G,H) 0x ## A ## B ## C ## D ## E ## F ## G ## H

EXPRESSION_LABEL HEXRESULT(RESULT_NIBBLE_7,RESULT_NIBBLE_6,RESULT_NIBBLE_5,RESULT_NIBBLE_4,RESULT_NIBBLE_3,RESULT_NIBBLE_2,RESULT_NIBBLE_1,RESULT_NIBBLE_0)

#undef HEXRESULTI
#undef HEXRESULT
#undef RESULT_NIBBLE_7
#undef RESULT_NIBBLE_6
#undef RESULT_NIBBLE_5
#undef RESULT_NIBBLE_4
#undef RESULT_NIBBLE_3
#undef RESULT_NIBBLE_2
#undef RESULT_NIBBLE_1
#undef RESULT_NIBBLE_0
#undef EXPRESSION
#undef EXPRESSION_LABEL


1 commentaires

S'étendant que les entiers de 64 bits n'en pensent pas (bien qu'il soit plus fastidieux que difficile), mais cela fonctionne correctement pour les entiers 32 bits. Ouch, bien que!