Что мы получаем при разыменовывании указателя на функцию?
int sum(int a, int b)
{
return a + b;
}
int main()
{
unsigned long long a = (unsigned long long)sum;
cout << ((int(*)(int, int))a)(3, 4) ;
cout << (*(int(*)(int, int))a)(3, 4) ;//почему это аналогично верхнему?
}
Почему эти 2 cout-A одинаковые по поведению?И что дает этот указатель во втором случае?
Вот еще,по моему аналогичный пример:
void message()
{
std::cout << "Hello, World" << std::endl;
}
int main()
{
void (*mg)();
mg=message;
message();
(*message)(); //Для чего писать такое разыменовывание,и что при этом происходит?
return 0;
}
Ответы (1 шт):
При разыменовывании указателя на функцию мы получаем lvalue, ссылающееся на эту функцию. Если применить оператор вызова функции к такому значению, то эта функция и будет вызвана. [expr.unary.op]/1 :
The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. [...]
Чтобы вызвать функцию, оператор вызова функции также можно применить непосредственно к указателю на функцию, без предварительного разыменовывания указателя. [expr.call]/1 :
A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of initializer-clauses which constitute the arguments to the function. [...] The postfix expression shall have function type or function pointer type. [...]
Чтобы присвоить указателю на функцию адрес функции, вы можете воспользоваться оператором &:
void message() {...}
...
void (*mg)() = &message;
Впрочем, использовать оператор & совсем не обязательно, так как существует неявное преобразование функции в указатель на функцию [conv.func]/1 :
An lvalue of function type
Tcan be converted to a prvalue of type “pointer toT”. The result is a pointer to the function.
Вот почему можно написать так:
void (*mg)() = message;
Напоследок замечу, что преобразование указателя на функцию в целочисленный тип — это условно-поддерживаемя конструкция. Стандарт языка не требует, чтобы такой код:
unsigned long long a = (unsigned long long)sum;
успешно компилировался. [expr.reinterpret.cast]/8 :
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. [...]