60 votes

Comment imprimer des pointeurs de fonction avec cout?

Je veux imprimer un pointeur de fonction à l'aide de cout, et a trouvé qu'il n'avait pas de travail. Mais il a travaillé, après je convertir le pointeur de fonction à (void *), afin de ne printf avec %p, tels que

#include <iostream>
using namespace std;

int foo() {return 0;}

int main()
{
    int (*pf)();
    pf = foo;
    cout << "cout << pf is " << pf << endl;
    cout << "cout << (void *)pf is " << (void *)pf << endl;
    printf("printf(\"%%p\", pf) is %p\n", pf);
    return 0;
}

J'ai compilé avec g++ et a obtenu des résultats comme ceci:

cout << pf est 1
cout << (void *)pf est 0x100000b0c
printf("%p", pf) est 0x100000b0c

Donc, ce n'est cout voir avec le type int (*)()? On m'a dit que le pointeur de fonction est considérée comme bool, est-il vrai? Et quel est le cout voir avec le type (void *)?

Merci à l'avance.

EDIT: de toute façon, nous pouvons observer le contenu d'un pointeur de fonction en la convertissant en (void *) et l'imprimer à l'aide de cout. Mais il ne fonctionne pas pour les membres des pointeurs de fonction et le compilateur se plaint de la conversion illégale. Je sais que membre des pointeurs de fonction est plutôt une structure compliquée autres que de simples pointeurs, mais comment pouvons-nous observer le contenu d'un membre des pointeurs de fonction?

11voto

avakar Points 20031

En ce qui concerne votre édition, vous pouvez imprimer le contenu de n’importe quoi en y accédant via le pointeur unsigned char . Un exemple pour les pointeurs vers les fonctions membres:

 #include <iostream>
#include <iomanip>

struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };

int main()
{
    void (foo3::*p)() = &foo::bar;

    unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
    unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);

    for (; first != last; ++first)
    {
        std::cout << std::hex << std::setw(2) << std::setfill('0')
            << (int)*first << ' ';
    }
    std::cout << std::endl;
}
 

8voto

Greg Bacon Points 50449

Vous pouvez penser à un pointeur de fonction comme étant l'adresse de la première instruction que la fonction de code machine. Un pointeur peut être considérée comme un bool: 0 est faux et tout le reste est vrai. Comme vous l'avez remarqué, lors de la coulée d' void * et donnée comme argument pour le flux opérateur d'insertion (<<), l'adresse est imprimée. (Vue strictement, en jetant un pointeur vers la fonction d' void * n'est pas défini.)

Sans les acteurs, l'histoire est un peu complexe. Pour la correspondance des fonctions surchargées ("résolution de surcharge"), un compilateur C++ regroupe un ensemble de fonctions candidates et de candidats sélectionne les "meilleurs viable", en utilisant des conversions implicites, si nécessaire. Les rides sont les règles d'appariement forme d'une commande partielle, de sorte que plusieurs best-viable correspond à provoquer une erreur d'ambiguïté.

Dans l'ordre de préférence, le processus de conversion standard (et bien sûr, il y a également défini par l'utilisateur et les points de suspension les conversions, et non détaillé) sont

  • exact (c'est à dire, pas de conversion nécessaire)
  • la promotion (par exemple, int de float)
  • d'autres conversions

La dernière catégorie comprend les booléens les conversions, et tout type pointeur peut être converti en bool: 0 (ou NULL) est false et tout le reste est true. Ce dernier apparaît comme étant l' 1 lorsqu'il est passé dans le flux opérateur d'insertion.

Pour obtenir de l' 0 au lieu de cela, changez d'initialisation de la

pf = 0;

Rappelez-vous que l'initialisation d'un pointeur avec une valeur zéro expression constante des rendements pointeur null.

2voto

Eli Bendersky Points 82298

La diffusion de pointeurs sur (void*) pour les imprimer sur cout est la bonne chose à faire en C ++ si vous souhaitez voir leurs valeurs.

1voto

John Dibling Points 56814

Sujet de votre question particulière,

comment pouvons-nous observer le contenu d'un membre des pointeurs de fonction?

La réponse est, autres que les convertissant en bool d'exprimer qu'il pointe vers quelque chose ou ça ne marche pas, vous ne pouvez pas "observateur" membre des pointeurs de fonction. Au moins pas dans un sens conforme. La raison en est parce que la norme interdit explicitement ceci:

4.12 note de bas de page 57:

57) La règle de conversion de les pointeurs pour les membres (à partir du pointeur de membre de la base de pointeur de membre de l' dérivé) apparaît inversé par rapport à la règle des pointeurs vers les objets (à partir de pointeur vers dérivé de pointeur à la base) (4.10, article 10). Cette inversion est nécessaires pour assurer la sécurité de type. Note qu'un pointeur de membre n'est pas un pointeur vers un objet ou un pointeur vers la fonction et les règles de conversions de tels pointeurs ne s'appliquent pas à des pointeurs vers les membres. En particulier, un pointeur de membre ne peut pas être converti pour un void*.

Pour exemple, voici un exemple de code:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

class Gizmo
{
public:
    void DoTheThing()
    {
        return;
    };


private:
    int foo_;
};

int main()
{
    void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;

    Gizmo g;
    (g.*fn)();  // once you have the function pointer, you can call the function this way

    bool b = fn;
//  void* v = (void*)fn;    // standard explicitly disallows this conversion
    cout << hex << fn;
    return 0;
}

Je remarque que mon débogueur (MSVC9) est capable de me dire le réel de l'adresse physique de la fonction de membre au moment de l'exécution, donc je sais qu'il doit y avoir un moyen d'obtenir cette adresse. Mais je suis sûr que c'est de la non-conforme, non-portable et implique sans doute de code machine. Si je devais aller dans cette voie, je voudrais commencer par prendre l'adresse du pointeur de fonction (par exemple, &fn), conversion de void*, et à partir de là. Cela permettrait également d'exiger de vous que vous connaissez la taille des pointeurs (différents sur les différentes plates-formes).

Mais je voudrais demander, aussi longtemps que vous pouvez convertir les etats-pointeur de fonction bool et d'évaluer l'existence d'un pointeur, pourquoi dans le code réel, auriez-vous besoin de l'adresse?

Sans doute la réponse à la dernière question est "afin que je puisse déterminer si un pointeur de fonction des points à la même fonction que l'autre." Juste assez. Vous pouvez comparer les pointeurs de fonction pour l'égalité:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

class Gizmo
{
public:
    void DoTheThing()
    {
        return;
    };

    **void DoTheOtherThing()
    {
        return;
    };**


private:
    int foo_;
};

int main()
{
    void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;

    Gizmo g;
    (g.*fn)();  // once you have the function pointer, you can call the function this way

    bool b = fn;
//  void* v = (void*)fn;    // standard explicitly disallows this conversion
    cout << hex << fn;

    **void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing;

    bool same = fnOther == fn;
    bool sameIsSame = fn == fn;**

    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X