Я разрабатываю программу на C ++, которая работает с адресами для различных переменных и функций.
Когда я компилировал свою программу в ОС на базе 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 вместо виртуального адреса.
Я очень ценю вашу помощь, ребята
Заранее спасибо
Азиз
Указатель преобразуется в другой тип, логический, потому что это указатель на функцию & нет перегрузок operator<<
в библиотеке iostrem для этих типов аргументов (потому что таких типов бесконечно много). Указатель указывает на некоторый ненулевой адрес, потому что он был инициализирован с адресом функции — поэтому преобразуется в 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;
}
Стандарт C ++ n3337 § 4.12 Булевы преобразования [conv.bool]
1 Значение арифметики, перечисления с незаданной областью, указателя или указателя
Тип члена может быть преобразован в тип значения типа bool. Ноль
значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется
ложно; любое другое значение преобразуется в true. Prvalue типа
std :: nullptr_t может быть преобразован в значение типа bool;
результирующее значение ложно.
<<
не имеет стандартной перегрузки, принимающей указатель на функцию; поэтому вместо этого указатель преобразуется в bool
(так как это законное неявное преобразование), давая 1
, или же true
если вы использовали std::boolalpha
манипулятор в потоке.
Если вам нужен адрес, вам придется явно преобразовать его в указатель объекта:
std::cout << reinterpret_cast<void*>(&Function1) << std::endl;
Если я изменю ваш код на следующий, адреса указателей функций будут отображаться правильно:
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
,