IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

[Préprocesseur] Opérateur concaténation, prise de tête


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut [Préprocesseur] Opérateur concaténation, prise de tête
    Bonjour,

    Etant sur un projet de gestion de logs, j'aurais besoin de concaténer un identificateur avec la valeur d'une variable. Or, j'ai beau retourner le problème dans tous les sens, j'ai du mal à voir...

    Par exemple, j'ai une variable n, dont je modifie la valeur au fur et à mesure du programme. J'ai une macro qui déclare une variable d'un identificateur donné, avec le suffixe dont la valeur est indiquée par n. Or, si je fais quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int n = 0;
     
    #define FOO(id) \
        int id ## n = 0;
     
    void bar(void) {
        FOO(prefixe);
    }
    J'imagine que je vais me retrouver avec un identificateur du type « prefixen » alors que je souhaitais avoir un identificateur « prefixe0 ». Ce que je demande est peut-être impossible, puisqu'il demande le contenu de la variable qui ne sera évaluée qu'à la compilation, et la phase du préprocesseur est antérieure. Merci de m'éclairer ; je m'avoue perplexe.

    Bonne journée et merci d'avance.

  2. #2
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Salut,

    Comme tu l'as dit, ça ne va pas être possible car le préprocesseur n'évalue pas le contenu des variables.

    Ce que tu cherches à faire n'est pas normal et dénote une incompréhension du problème de ta part.

    Si tu veux qu'on te donne une solution adaptée il faudra que tu nous expliques plus précisément le projet. Sinon utilise des tableaux ou un sprintf ou que sais-je.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    En fait, je suis en train de recoder un mécanisme d'exceptions (avec setjmp et longjmp). J'aimerais limiter le nombre d'identificateurs réservés, en attribuant un identificateur du style « variableN » à chaque appel d'une macro donnée.

    Je m'explique : j'ai une macro qui déclare une variable. Or, si j'appelle plusieurs fois cette macro dans un même bloc fonctionnel, je me retrouve avec un conflit d'identificateurs qui se retrouvent dans un même espace de nom.

    Ce que j'aurais aimé faire, c'est ajouter un suffixe différent à mon identificateur à chaque appel de la macro (et ainsi déclarer des identificateurs différents à chaque appel).

    Ce que j'avais prévu de faire, c'est d'englober mon ensemble par un do ... while(0) pour que l'identificateur soit déclaré uniquement dans la boucle (ainsi, sa portée serait limitée ; mais on aurait des problèmes de variables masquées lors d'imbrications). En plus du problème de l'imbrication, le programmeur devrait être obligé de rajouter un appel de macro de fin pour terminer la boucle, ce qui est assez désagréable et surprenant au premier abord.

    Si vous voulez vraiment du code, en voici (je l'ai simplifié pour les besoins du forum)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #define try \
        do { \
            struct { \
                int type; \
                jmp_buf env; \
            } _catch; \
            if (!(_catch.type = setjmp(_catch.env)))
     
    #define catch(id) \
            else { \
                int id = _catch.type \
        
    #define throw(t) \
        longjmp(_catch.env, t)
     
    #define endtrycatch \
            } \
        } while (0)
    J'aimerais ainsi me débarrasser de la macro « endtrycatch ». L'accolade précédant le } while(0) pourra être supprimée au besoin (il suffira de se débrouiller avec un for qui déclare la variable dans son champ d'initialisation et boucle une seule fois). C'est donc le do ... while(0) que j'aimerais enlever. Auriez-vous une idée ?

    Note : les identificateurs commencent par un underscore, mais on va dire que je me rapporte à « l'implémentation ». Bien que pas terrible vis-à-vis de la norme, ça évitera les conflits d'identificateurs.

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Salut,

    avec le préprocesseur de gcc tu as accès à la macro __COUNTER__ qui est incrémentée à chaque utilisation :
    3.7.2 Common Predefined Macros

    The common predefined macros are GNU C extensions. They are available with the same meanings regardless of the machine or operating system on which you are using GNU C or GNU Fortran. Their names all start with double underscores.

    __COUNTER__
    This macro expands to sequential integral values starting from 0. In conjunction with the ## operator, this provides a convenient means to generate unique identifiers. Care must be taken to ensure that __COUNTER__ is not expanded prior to inclusion of precompiled headers which use it. Otherwise, the precompiled headers will not be used.


    ... mais si tu veux des exemples de raii codé en c tu peux t'inspirer de :

    http://www.di.unipi.it/~nids/docs/lo...row_catch.html
    ou
    http://code.google.com/p/libex/

    par exemple.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    Merci pour la macroconstante __COUNTER__, je ne connaissais pas. Il y a tout de même quelque chose qui me dérange dans celle-ci.

    - Premièrement, je dois réutiliser cette variable pour obtenir l'identificateur plusieurs fois. Cela induit donc une multiple utilisations de __COUNTER__, qui devrait s'incrémenter à chaque fois que j'essaye de concaténer (même dans le bloc catch correspondant).
    - Deuxièmement, ce n'est qu'une extension gcc. Vu que c'est censé être un code d'exemple, j'aurais préféré quelque chose d'un peu plus portable. Maintenant, ce n'est peut-être pas possible...

    Pour les exemples d'exceptions, je les avais déjà vus, merci quand même.

    Merci pour vos deux réponses.

Discussions similaires

  1. Réponses: 4
    Dernier message: 23/10/2006, 09h09
  2. Réponses: 7
    Dernier message: 23/12/2005, 16h21
  3. Catalogue tables : prise de tête
    Par KinF dans le forum Requêtes
    Réponses: 5
    Dernier message: 02/12/2005, 01h04
  4. [MFC] Prise de tête avec UpdateAllViews
    Par pataguillon dans le forum MFC
    Réponses: 13
    Dernier message: 11/08/2005, 13h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo