Печать указателя на поле члена - PullRequest
0 голосов
/ 19 октября 2011

Я отлаживал некоторый код, включающий указатели на поля-члены, и решил распечатать их, чтобы увидеть их значения. У меня была функция, возвращающая указатель на член:

#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;
    }
}

Я пытался использовать cout:

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

Я получил 1 and 0. Я думал, что числа указывают положение поля внутри struct (то есть 1 равно y и 0 равно x), но нет, напечатанное значение на самом деле 1 для не нулевой указатель и 0 для нулевого указателя. Я предполагаю, что это стандартно-совместимое поведение (хотя это и не полезно) - я прав? Кроме того, может ли совместимая реализация C ++ всегда печатать 0 для указателей на члены? Или даже пустая строка?

И, наконец, как я могу напечатать указатель на член осмысленным образом? Я придумал два уродливых способа:

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!

Есть ли лучшие способы?

Ответы [ 4 ]

2 голосов
/ 19 октября 2011

Указатели на участников не так просты, как вы думаете. Их размер изменяется от компилятора к компилятору и от класса к классу в зависимости от того, имеет ли класс виртуальные методы или нет, и имеет ли он множественное наследование или нет. Предполагая, что они имеют размер, это не правильный путь. Что вы можете сделать, это напечатать их в шестнадцатеричном формате:

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
} // ()

Однако я не уверен, насколько полезной будет эта информация для вас, поскольку вы не знаете, какова структура указателей и что означает каждый байт (или несколько байтов).

1 голос
/ 19 октября 2011

Указатели членов не являются обычными указателями.Перегрузок, которые вы ожидаете для <<, на самом деле не существует.

Если вы не возражаете против какого-либо типа наказания, вы можете взломать что-нибудь, чтобы напечатать фактические значения:

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';
}
0 голосов
/ 05 июня 2018

Я думаю, вы должны использовать printf для решения этой проблемы

 #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;
}
0 голосов
/ 20 октября 2011

Вы можете отобразить необработанные значения этих указателей на элементы следующим образом:

#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 ;
  }

Вы получаете предупреждения о нарушении строгих правил сглаживания (см. эту ссылку ), но в результате вы можете ожидать:

0, 0x4, 0x8

Тем не менее, компилятор может свободно реализовывать функции указателя на член, как ему угодно, поэтому нельзя полагаться на значимость этих значений.

...