Как распечатать указатели функции с судом?

49
задан ibread 14 January 2010 в 04:46
поделиться

6 ответов

На самом деле существует перегрузка оператора < <, которая выглядит примерно так:

ostream & operator <<( ostream &, const void * );

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

Edit: Стандарт C++ задает:

4,12 Логические преобразования

1 Значение арифметики, перечисление, указатель или указатель на тип члена может быть преобразован в rvalue типа bool.

Это единственное преобразование, указанное для указателей функций.

42
ответ дан 7 November 2019 в 11:51
поделиться

возможно (в одно время я остаюсь пересекающимся об адресе функции) одно из решения)))

#include <iostream>     
#include <stdlib.h>

void alexf();

int main()
{ 
    int int_output;

    printf("printf(\"%%p\", pf) is %p\n", alexf);

    asm( "movl %[input], %%eax\n"                
         "movl %%eax, %[output]\n" 
         : [output] "+m" (int_output)
         : [input] "r" (&alexf)
         : "eax", "ebx"
    );

        std::cout<<"" <<std::hex<<int_output <<""<<std::endl;
    return 0;
}

void  alexf() {  }

передача указателя на функцию (&alexf) или другого указателя с помощью & ограничение использования r. Позвольте gcc для использования регистра для входного параметра)).

0
ответ дан 7 November 2019 в 11:51
поделиться

Что касается вашего редактирования, вы можете распечатать содержимое чего-либо путем доступа к нему через unsigned Char указатель. Пример для указателей к функциям-членам:

#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;
}
11
ответ дан 7 November 2019 в 11:51
поделиться

Что касается вашего конкретного вопроса,

Как мы можем наблюдать за содержанием Указатели функции участника?

Ответ, кроме преобразования их в BoOL, чтобы выразить, что он указывает на что-то или нет, вы не можете «Наблюдать». По крайней мере, не совместимым способом. Причина в том, что стандарт явно отложит это:

4.12 сноска 57:

57) Правило для преобразования Указатели членам (от указателя на Член базы для указателя на члена полученный) кажется перевернутым по сравнению с правило для указателей на объекты (от Указатель на получение указателя на базу) (4.10, пункт 10). Эта инверсия необходимо обеспечить безопасность типа. Примечание что указатель на члена не является указатель на объект или указатель на Функция и правила преобразования таких указателей не применяются к Указатели членам. в частности, Указатель члена не может быть преобразован избежать*.

Например, вот образец кода:

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

я отмечаю, что мой отладчик (MSVC9) может сказать мне фактический физический адрес функции члена во время выполнения, поэтому я знаю, что должен быть какой-то способ на самом деле получить это адрес. Но я уверен, что это не соответствует, не портативно и, вероятно, включает в себя машинный код. Если бы я пошел по этой дороге, я бы начну сдал адрес указателя функции (например, & Fn ), отлив на то, что пустоту * и идет оттуда. Это также потребовало бы, чтобы вы знали размер указателей (разные на разных платформах).

Но я бы спросил, до тех пор, пока вы можете преобразовать указатель функции участника в Bool и оценить существование указателя, почему в реальном коде вам нужен адрес?

Предположительно, ответ на последний вопрос «Итак, я могу определить, указывает ли одна функция указателя к той же функции, что и другая». Справедливо. Вы можете сравнить функцию указателей для равенства:

#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;
}
1
ответ дан 7 November 2019 в 11:51
поделиться

Вы можете подумать о функциональном указателе как адрес первой инструкции в машинном коде этой функции. Любой указатель можно рассматривать как BOOL : 0 является ложным, и все остальное верно. Как вы наблюдали, при отбросе к void * и дан в качестве аргумента для оператора вставки потока ( << ), адрес печатается. (Просматривается строго, литье указателя на функцию void * не определено.)

Без отличия история - это небольшой комплекс. Для сопоставления перегруженных функций («Разрешение перегрузки») компилятор C ++ собирает набор функций-кандидатов, и из этих кандидатов выбирает «лучший жизнеспособный», используя неявные преобразования, если необходимо. Морщина - это правила сопоставления формируют частичный порядок, поэтому множество лучших жизнеспособных совпадений вызывают ошибку двусмысленности.

В порядке предпочтения, стандартные преобразования (и, конечно же, там также определенные пользователем и конверсию ELLIPSIS, не детализированы)

  • точные совпадения (, то есть , не требуется преобразование)
  • Продвижение (, например , INT на поплавок )
  • Другие преобразования

В последнюю категорию включает в себя логические преобразования, и любой тип указателя может быть преобразован в Bool : 0 (или NULL ) IS false и все остальное - это true . Последнее отображается как 1 , когда передается оператору вставки потока.

Вместо этого 0 вместо этого измените инициализацию на

pf = 0;

Помните, что инициализация указателя с нулевым постоянным выражением дает нулевой указатель.

7
ответ дан 7 November 2019 в 11:51
поделиться

Указатели литья в (пустота *) , чтобы распечатать их в Cout , это правильная вещь (TM), чтобы сделать в C ++, если вы хотите увидеть их ценности.

2
ответ дан 7 November 2019 в 11:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: