Question

je débogage du code impliquant des pointeurs vers des champs membres, et moi avons décidé de les imprimer pour voir leurs valeurs. J'ai eu une fonction renvoyant un pointeur vers un membre:

#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
    switch (what) {
    case 0: return &test::x;
    case 1: return &test::y;
    case 2: return &test::z;
    default: return NULL;
    }
}

J'ai essayé d'utiliser cout:

#include <iostream>
int main()
{
    std::cout << select(0) << " and " << select(3) << '\n';
}

Je suis 1 and 0. Je pensais que les chiffres indiqués la position du champ à l'intérieur du struct (qui est, 1 est y et 0 est x), mais non, la valeur imprimée est en fait 1 pour pointeur non nul et 0 pour pointeur NULL. Je suppose que cela est un comportement conforme aux normes (même si ce n'est pas utile) - suis-je pas? De plus, est-il possible pour une mise en œuvre c ++ compatible pour imprimer toujours 0 pour-à-pointeurs membres? Ou même une chaîne vide?

Et enfin, comment puis-je imprimer un pointeur à membre d'une manière significative? Je suis venu avec deux façons laid:

printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?

ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!

Toute meilleures façons?

Était-ce utile?

La solution

Les pointeurs membres ne sont pas des pointeurs ordinaires. Les surcharges que vous attendez pour << ne sont pas là en fait.

Si vous ne me dérange pas un certain type calembour, vous pouvez pirater quelque chose pour imprimer les valeurs réelles:

int main()
{
  ptr_to_member a = select(0), b = select(1);
  std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
            << *reinterpret_cast<uint32_t*>(&b) << " and "
            << sizeof(ptr_to_member) << '\n';
}

Autres conseils

Pointeurs aux membres ne sont pas aussi simples que vous pouvez penser. Leur taille change de compilateur compilateur et de classe en classe, selon que la classe a des méthodes virtuelles ou non et si elle a l'héritage multiple ou non. Si l'on suppose qu'ils sont int taille est pas la bonne façon d'aller. Ce que vous pouvez faire est de les imprimer en hexadécimal:

void dumpByte(char i_byte)
{
    std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
    std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()

template <typename T>
void dumpStuff(T* i_pStuff)
{
    const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
    size_t size = sizeof(T);
    while (size)
    {
        dumpByte(*pStuff);
        ++pStuff;
        --size;
    } // while
} // ()

Cependant, je ne suis pas sûr de l'utilité que l'information sera à vous puisque vous ne savez pas quelle est la structure des pointeurs et ce que chaque octet (ou plusieurs octets) dire.

Vous pouvez afficher les valeurs brutes de ces pointeur à des membres comme suit:

#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
    switch (what) {
    case 0: return &test::x;
    case 1: return &test::y;
    case 2: return &test::z;
    default: return NULL;
    }
}

int main()
  {
  ptr_to_member x = select(0) ;
  ptr_to_member y = select(1) ;
  ptr_to_member z = select(2) ;
  std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
  }

Vous obtenez des avertissements au sujet enfreindre les règles anti-aliasing strictes (voir ce lien ), mais le résultat est ce que vous pourrait attendre:

0, 0x4, 0x8

Cependant, le compilateur est libre de mettre en œuvre la fonctionnalité pointeur à membre mais il aime, vous ne pouvez pas compter sur ces valeurs étant significative.

Je pense que vous devriez utiliser printf pour résoudre ce problème

 #include <stdio.h>

struct test{int x,y,z;}
int main(int argc, char* argv[])
{
  printf("&test::x=%p\n", &test::x);
  printf("&test::y=%p\n", &test::y);
  printf("&test::z=%p\n", &test::z);
  return 0;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top