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

Langage C++ Discussion :

Assigner une adresse à une simple variable. (Pas un pointeur)


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Assigner une adresse à une simple variable. (Pas un pointeur)
    Salut, je cherche à lire et écrire des données, mais je ne veux pas que les données soit lue ou écrite deux fois si un pointeur pointe sur une variable.

    J'ai donc fais ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int var = 5;
    int* pvar = &var;
    std::ofstream file;
    OTextArchive ota(file);
    ota(var);
    ota(pvar);

    Dans l'archive, je stocke l'adresse de var que je fais correspondre à un id dans une std::map, j'écris l'id et le contenu de var, ensuite, je recherche l'adresse correspondant à l'id et j'écris uniquement l'id pour dire que j'ai un pointeur vers la var. (Je ne peut pas écrire les adresses car elles peuvent changer d'une exécution à l'autre du programme)

    Lors de la lecture je fais l'inverse, c'est à dire que je lis l'id et le contenu de var, et je stocke l'adresse et l'id dans une std::map, ensuite, je lis l'id, et je recherche l'adresse correspondante dans la std::map que j'affecte au pointeur pvar.

    Bref, le code ressemble à ceci pour l'écriture :

    Code cpp : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
                /**
                * \fn void operator(T& data, D...)
                * \brief write a fundamental type into the archive.
                * \param T& the data to write.
                * \param D... used for SFINAE.
                */
                template <typename T,
                          class... D,
                          class = typename std::enable_if<std::is_fundamental<T>::value>::type>
                void operator() (T& data, D...) {
                    std::map<unsigned long long int, long long int>::iterator it = adresses.find(reinterpret_cast<long long int>(&data));
                    if (it != adresses.end()) {
                            //Variable already written, write just the variable id.
                            buffer<<it->second<<std::endl;
                    } else {
                            //Variable not writtent, write corresponding id and the variable's content.
                            std::pair<unsigned long long int, long long int> newAddress (reinterpret_cast<long long int>(&data), nbSerialized);
                            adresses.insert(newAddress);
                            nbSerialized++;
                            buffer<<newAddress.second<<std::endl;
                            buffer<<data;                      
                    }              
                }
                /**
                * \fn void operator(T* data, D...)
                * \brief write pointer to a fundamental type into the archive.
                * \param T* the pointer to write.
                * \param D... used for SFINAE.
                */
                template <typename T,
                      class... D,
                      class = typename std::enable_if<std::is_fundamental<T>::value>::type>
                void operator() (T* data, D...) {
                    //Pointer not null, we can write the variable.
                    if (data != nullptr) {
                        std::map<unsigned long long int, long long int>::iterator it = adresses.find(reinterpret_cast<long long int>(data));
                        //The variable content has already been written, write just the variable's id.
                        if (it != adresses.end()) {
                            buffer<<it->second<<std::endl;
                        //The variable content has not been writtent, write the variable's id and content.
                        } else {
                            std::pair<unsigned long long int, long long int> newAddress (reinterpret_cast<long long int>(data), nbSerialized);
                            adresses.insert(newAddress);
                            serialized++;
                            buffer<<newAddress.second<<std::endl;
                            buffer<<(*data);
     
                        }
                    //Pointer is null, write -1.
                    } else {
                        long long int id = -1;
                        buffer<<id<<std::endl;
                    }
                }

    Lors de la lecture, je fais l'inverse :

    Code cpp : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
                //Fundamentals.
                /**
                * \fn void operator(T& data, D...)
                * \brief read a fundamental type from the archive.
                * \param T& the data to read.
                * \param D... used for SFINAE.
                */
                template <typename T,
                      class... D,
                      class = typename std::enable_if<std::is_fundamental<T>::value>::type>
                void operator() (T& data, D...) {
                     long long int id;
                     buffer>>id;
                     char space;
                     buffer.get(space);
                     std::map<long long int, unsigned long long int>::iterator it = adresses.find(id);
                     //Variable has already been read, we affect its address.
                     if (it != adresses.end()) {
                            //Error, it won't compile.
                            &data = reinterpret_cast<T*> (it->second);
                            //Variable has not been read yet, store its address and its id and read the variable's content.
                     } else {                        
                            std::pair<long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data));
                            adresses.insert(newAddress);
                            nbDeserialized++;
                            buffer>>data;
                            char space;
                            buffer.get(space);
                     }                
                }
                /**
                * \fn void operator(T& data, D...)
                * \brief read a pointer to a fundamental type from the archive.
                * \param T& the data to read.
                * \param D... used for SFINAE.
                */
                template <typename T,
                      class... D,
                      class = typename std::enable_if<std::is_fundamental<T>::value>::type>
                void operator() (T*& data, D...) {
                    long long int id;
                    buffer>>id;
                    char space;
                    buffer.get(space);
                    if (id != -1) {
                        //Variable has already been read, we affect its address.
                        std::map<long long int, unsigned long long int>::iterator it = adresses.find(id);
                        if (it != adresses.end()) {
                            data = reinterpret_cast<T*> (it->second);
                        //Variable has not been read yet, store its address and its id and read the variable's content.
                        } else {
                            std::pair<long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data));
                            adresses.insert(newAddress);
                            nbDeserialized++;
                            data = new T();
                            buffer>>(*data);                        
                        }
                    } else {
                        data = nullptr;
                    }
                }

    Dans le fichier j'ai donc ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    0 5 //Variable id and content.
    0 //Variable id. (pointer to first variable)
    Écrit dans cet ordre là, pas de problème, par contre si je fais ça :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int var = 5;
    int* pvar = &var;
    std::ofstream file;
    OTextArchive ota(file);
    ota(pvar);
    ota(var);

    Cela va poser problème car à la lecture il va allouer le pointeur pvar et lui donner la valeur 5, ensuite il va donner l'adresse du pointeur pvar à var.

    Hors en c++ on ne peut pas faire ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //Error, it won't compile.
    &data = reinterpret_cast<T*> (it->second);

    Du coup je cherche un code en assembleur que j'insérerai dans le code c++ et qui me permettrait de changer l'adresse de la variable.
    Mais je ne sais pas comment récupérer une référence vers la variable data dans le code assembleur pour changer son adresse et lui donner celle de mon pointeur.


    Est ce que quelqu'un sait comment faire ?

    Merci d'avance.

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Une adresse n'est valable que pour une exécution d'un programme.

    Tu peux stocker des écarts entre pointeurs, et encore, seulement si tu es en mesure de garantir la contiguité du bloc mémoire.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Invité
    Invité(e)
    Par défaut
    Salut, j'ai essayer ça :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int* pvar = new int(5);
    int var;
    asm ("lea ebx, pvar");
    asm ("mov var, ebx");

    Mais j'ai cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|42|error: unknown use of instruction mnemonic without a size suffix|
    Sachant que j'ai un processeur intel, quel code dois je mettre ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Du coup je cherche un code en assembleur que j'insérerai dans le code c++ et qui me permettrait de changer l'adresse de la variable.
    A ma connaissance tu peux pas (et l'asm ne t'aidera pas ici : c'est pas possible en asm non plus).
    Par contre tu peux allouer ta variable à l'adresse qui te plait avec un placement new, ou plus simplement utiliser une référence.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    T *addr = reinterpret_cast<T*> (it->second);
    T *pData = new(addr) T;
     
    // ou 
     
    T& data = *reinterpret_cast<T*> (it->second);
    (J'ai par contre pas vraiment compris le but, j'espère ne pas répondre complètement à coté.)

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ok c'est la réponse que je cherchais, je vais utiliser une référence, merci!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 05/01/2017, 09h48
  2. [XL-2010] Copie d'un tableau d'une feuille à une autre : une cellule ne se recopie pas
    Par mchouv dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 25/07/2014, 12h47
  3. Recherche d'une regex toute simple (mais pas pour moi)
    Par rambc dans le forum Général Python
    Réponses: 7
    Dernier message: 15/04/2009, 15h23
  4. [FLASH 8] récuperer dans une BDD une adresse email
    Par iceman2001 dans le forum Flash
    Réponses: 4
    Dernier message: 06/04/2006, 17h39
  5. [PHPMailer] Les mails avec une adresse extérieure ne partent pas
    Par captaindidi dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 06/01/2006, 19h11

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