web-dev-qa-db-fra.com

Le préprocesseur C peut-il effectuer une arithmétique entière?

Comme le dit la question, le préprocesseur C est-il capable de le faire?

Par exemple.:

#define PI 3.1416
#define OP PI/100
#define OP2 PI%100

Existe-t-il un moyen de calculer OP et/ou OP2 pendant la phase de prétraitement?

24
Schim

Arithmétique entière? Exécutez le programme suivant pour le découvrir:

#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
 }

La réponse est "oui", il existe un moyen pour que le préprocesseur effectue une arithmétique entière, qui consiste à l'utiliser dans une condition de préprocesseur.

Notez cependant que vos exemples ne sont pas de l'arithmétique entière. Je viens de vérifier et le préprocesseur de gcc échoue si vous essayez de lui faire faire des comparaisons flottantes. Je n'ai pas vérifié si la norme autorise jamais l'arithmétique à virgule flottante dans le préprocesseur.

L'expansion régulière des macros n'évalue pas les expressions entières, elle le laisse au compilateur, comme on peut le voir en prétraitant (-E dans gcc) les éléments suivants:

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
    int i = ONEPLUSONE;
#endif

Le résultat est int i = (1 + 1); (plus probablement quelques trucs pour indiquer les noms de fichiers source et les numéros de ligne et autres).

34
Steve Jessop

Le code que vous avez écrit ne fait pas faire de calcul au préprocesseur. Un #define fait un remplacement de texte simple, donc avec ceci défini:

#define PI 3.1416
#define OP PI/100

Ce code:

if (OP == x) { ... }

devient

if (3.1416/100 == x) { ... }

puis il est compilé. À son tour, le compilateur peut choisir de prendre une telle expression et de la calculer au moment de la compilation et de produire un code équivalent à ceci:

if (0.031416 == x) { ... }

Mais c'est le compilateur, pas le préprocesseur.

Pour répondre à votre question, oui, le préprocesseur PEUT faire de l'arithmétique. Cela peut être vu lorsque vous écrivez quelque chose comme ceci:

#if (3.141/100 == 20)
   printf("yo");
#Elif (3+3 == 6)
   printf("hey");
#endif
19
shoosh

Oui, cela peut être fait avec le préprocesseur Boost. Et il est compatible avec le C pur, vous pouvez donc l'utiliser dans des programmes C avec des compilations C uniquement. Votre code implique cependant des nombres à virgule flottante, donc je pense que cela doit être fait indirectement.

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

Cette procédure préalable à (vérifier avec gcc -S)

int div = 512;
int rem = 0;

Merci à ce fil.

7
highBandWidth

[~ # ~] oui [~ # ~] , je veux dire: ça peut faire de l'arithmétique :)

Comme démontré dans 99 bouteilles de bière .

7
pmg

Oui.

Je ne peux pas croire que personne ne s'est encore lié à un certain gagnant du concours C obscurci. Le gars a implémenté une ALU dans le préprocesseur via des inclusions récursives. Ici est l'implémentation, et ici est quelque chose d'une explication.

Maintenant, cela dit, vous ne voulez pas faire ce que ce gars a fait. C'est amusant et tout, mais regardez les temps de compilation dans son fichier d'indices (sans parler du fait que le code résultant n'est pas gérable). Plus communément, les gens utilisent le pré-processeur strictement pour le remplacement de texte, et l'évaluation de l'arithmétique entière constante se produit soit au moment de la compilation soit au moment de l'exécution.

Comme d'autres l'ont noté cependant, vous pouvez faire de l'arithmétique dans les instructions #if.

4
Stephen Canon

Soyez prudent lorsque vous faites de l'arithmétique: ajoutez des parenthèses.

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

Si vous utilisez quelque chose comme:

unsigned int i = TOTALSIZE/4;

et attendez-vous à ce que je sois 3, vous obtiendrez 4 + 2 = 6 à la place. Ajouter des parenthèses:

#define TOTALSIZE (SIZE4 + SIZE8)
2
Phil