2015-12-13 1 views
6

я определил некоторые функции и напечатать их адрес, как это:C++ указатель на функцию не изменилась

#include<iostream> 
#include <string> 

using std::cout; 

std::string func() 
{ 
    return "hello world\n"; 

} 

int func2(int n) 
{ 
    if (n==0) 
    { 
     cout << func2 << std::endl; 
     return 1; 
    } 

    cout << func2 << std::endl; 

    return n + func2(n - 1); 
} 

//================================================ 
int main() 
{ 
    int (*fun)(int) = func2; 

    cout << fun; 

    cout << std::endl << func2(3); 
} 

Когда я печатаю имя функции (адрес) все они печатают 1 на мой компилятор (Mingw GCC 4.8) ,

Все хорошо?

ответ

0

You» не печатайте адрес, потому что он теперь преобразован в логическое значение.

Но вы можете это сделать, например. это:

std::cout << reinterpret_cast<unsigned long long int *>(func2) << std::endl; 

Теперь вы получите фактический адрес.

+0

Предполагая, что размер указателя функции не превышает размер 'unsigned long long int'. Вы также должны добавить 'const' для броска, чтобы предотвратить несчастные случаи. –

+1

Да, ну ... в C++ 11 длинный длинный не менее 64 бит. – juzzlin

+0

Итак? Что, если указатели 128-бит в будущем? Как только они были всего лишь 16 бит. –

3

Это не существует перегрузки operator<< для std::ostream, который принимает указатель на функцию. Таким образом, предпочтительна перегрузка operator<<(std::ostream&, bool). Адрес функции всегда оценивается до true при преобразовании в bool. Таким образом, 1 печатается.

Alternatevely, если указатель на функцию не больше, чем размер указателя данных, вы можете отдать свой указатель на функцию к void* через reinterpret_cast и вызвать перегрузку operator<<(std::ostream&, void*) и, таким образом, получить фактический адрес функции печати.

int (*fun)(int) = func2; 
std::cout << reinterpret_cast<void*>(fun) << std::endl; 

Live Demo

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

В качестве альтернативы, и, по моему скромному мнению, правильно, вы можете форматировать указатель на функцию в качестве char буфера массива и преобразовать его адрес в строку следующим образом:

unsigned char *p = reinterpret_cast<unsigned char*>(&func2); 
std::stringstream ss; 
ss << std::hex << std::setfill('0'); 
for(int i(sizeof(func2) - 1); i >= 0; --i) ss << std::setw(2) 
               << static_cast<unsigned int>(p[i]); 
std::cout << ss.str() << std::endl; 

Live Demo

+1

Предполагая, что размер указателя функции не превышает размер указателя данных. Вы также должны добавить 'const' для броска, чтобы предотвратить несчастные случаи. –

+0

@NeilKirk Это правильно. – 101010

+0

примечание: это преобразование в 'void *' не требуется для существования –