в Linux при печати адресов функций всегда печатается 1 (С++)

Я разрабатываю программу на С++, которая работает с адресами для разных переменных и функций.

Когда я скомпилировал свою программу в ОС на базе Linux, все функции, включая основную, получили адрес 1 вместо 8-значного шестнадцатеричного числа, как другие переменные, чего не было в Windows.

Я написал этот небольшой фрагмент кода, чтобы объяснить проблему

#include <iostream>
using namespace std;
void Function1();
void Function1()
{
}
int main()
{
int tmp;
void (*a) ()=&Function1;
cout<<a<<endl;
cout<<&Function1<<endl;
cout<<&main<<endl;
return 0;
}

для всех 3 вызовов cout вместо виртуального адреса выводится 1.

Я очень ценю вашу помощь, ребята

Заранее спасибо Азиз


person Abdulaziz Aldyaf    schedule 28.08.2014    source источник
comment
чего не произошло в Windows Это должно было произойти.   -  person Lightness Races in Orbit    schedule 28.08.2014
comment
@LightnessRacesinOrbit Я только что попробовал, действительно не получилось, VS2013   -  person 4pie0    schedule 28.08.2014
comment
@0d0a: Ха, то же самое в VS2012. Это ошибка в одном или другом. stackoverflow.com/q/25540033/560648   -  person Lightness Races in Orbit    schedule 28.08.2014
comment
пожалуйста, исправьте отступ   -  person phuclv    schedule 28.08.2014


Ответы (3)


Указатель преобразуется в другой тип, boolean, потому что это указатель на функцию, и в библиотеке iostrem нет перегрузок operator<< для этих типов аргументов (поскольку таких типов бесконечное количество). Указатель указывает на какой-то ненулевой адрес, потому что он был инициализирован адресом функции, поэтому он преобразуется в 1 (только адрес 0x0 даст вам логический 0).

Решение

Чтобы подтвердить правильное поведение, вы должны привести указатель к void*, чтобы вы могли использовать перегрузку operator<< для void*, которая является

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

Пример:

void Function1(){}

int main() {
    void ( *a) () = &Function1;
    cout << ( void*)( a) << endl;
    /* or better - being explicit about harshness of this design */
    cout << reinterpret_cast< void*> ( a) <, endl;
}

http://ideone.com/Fne4Mu


C++ Standard n3337 § 4.12 Логические преобразования [conv.bool]

1 Значение арифметики, перечисления с незаданной областью, указателя или указателя на член может быть преобразовано в значение prvalue типа bool. Нулевое значение, значение нулевого указателя или значение нулевого указателя элемента преобразуется в значение false; любое другое значение преобразуется в true. Значение prvalue типа std::nullptr_t можно преобразовать в значение prvalue типа bool; результирующее значение ложно.

person 4pie0    schedule 28.08.2014

<< не имеет стандартной перегрузки, использующей указатель на функцию; поэтому вместо этого указатель преобразуется в bool (поскольку это законное неявное преобразование), давая 1 или true, если вы использовали манипулятор std::boolalpha в потоке.

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

std::cout << reinterpret_cast<void*>(&Function1) << std::endl;
person Mike Seymour    schedule 28.08.2014

Если я изменю ваш код на следующий, адреса указателей функций будут отображаться правильно:

void Function1() {
}

int main() {
    void*a = (void*)&Function1;
    cout<<a<<endl;
    cout<< (void*)&Function1<<endl;
    cout<< (void*)&main<<endl;
    return 0;
}

Выход:

0x8048710
0x8048710
0x8048570

См. рабочий образец здесь.


Проблема в том, что для

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

но не для указателей функций

ostream& operator<<(ostream&,void (Function1Type*)())

и наименее валидные конверсионные розыгрыши

ostream& operator<<(ostream&,bool)

где все, кроме 0x00000000, равно true.

person πάντα ῥεῖ    schedule 28.08.2014
comment
@AbdulazizAldyaf Если вы хотите отблагодарить меня или сообщество, вы можете рассмотреть возможность принятия этого ответа: просто нажмите на большую белую галочку, только что оставленную под моим постом (за это вы даже получите репутацию). - person πάντα ῥεῖ; 29.08.2014