Как работает оператор typedef для указателя на функцию
Я думаю, что я могу страдать от страшной болезни "случайного программиста", по крайней мере, когда дело доходит до typedefs и указателей функций. Поэтому я экспериментировал со всевозможными комбинациями, включающими их, чтобы проанализировать результаты, основанные на всех выходных данных, которые я получаю.
но поскольку я продолжал пробовать разные комбинации, вместо анализа результатов я теперь просто потерялся в процессе.
Я надеюсь, что вы, ребята, поможете мне разобраться в этом беспорядок.
первый пример кода
typedef void (print)(void);
void do_something (void) { printf("Hello Worldn"); }
print *pr;
pr = &do_something;
pr(); // Hello World
второй пример кода
typedef void (print)(void);
void do_something (void) { printf("Hello Worldn"); }
print *pr;
pr = do_something;
pr(); // Hello World
как работают оба вышеприведенных примера кода, как будто " & " не влияет на имя функции
третий пример кода
typedef void (print)(void);
void do_something (void) { printf("Hello Worldn"); }
print pr;
pr = do_something; // compile error
pr = &do_something; // compile error
pr();
Я надеялся, что одно из вышеупомянутых заданий будет работать здесь, но черт! Я действительно не понимаю указателей функций (и, возможно, typedef тоже).
4 ответов
адрес имени функции и простое имя функции означают одно и то же, поэтому &
не влияет на имя функции.
аналогично, при использовании указателей функций многократное разыменование не является проблемой:
#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }
int main(void)
{
print *f1 = dosomething;
print *f2 = &dosomething;
f2();
(f1)();
(*f1)();
(**f2)();
(***f1)();
(****f2)();
(*****f1)();
}
что компилируется в:
gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -std=c99 xx.c -o xx
Я бы не стал утверждать, что несколько звезд-это хороший стиль-это не так. Это странно, и (да, вы можете сказать это) порочные'. Одного достаточно (и одна звезда в основном для таких людей, как я, кто научился программировать на C до стандарта, сказал: "нормально вызывать функцию с помощью указателя без использования (*pointer_to_function)(arg1, arg2)
нотации; вы можете просто написать pointer_to_function(arg1, arg2)
если вам нравится"). Да, это странно. Нет, ни один другой тип (или класс типов) не проявляет такого же поведения, слава богу.
дело в указателях функций заключается в том, что они являются функцией указатели! : -) вот как вы получаете свой третий образец для работы:
#include <stdio.h>
typedef void (*print)(void);
// ^
void do_something (void) { printf("Hello World\n"); }
int main (void) {
print pr;
pr = do_something; // &do_something would also work.
pr();
return 0;
}
С точки зрения того, используете ли вы funcName
или &funcName
, это не имеет значения (по крайней мере, в C). Раздел 6.3.2.1 Lvalues, arrays and function designators
гласит:
обозначение функции-это выражение, имеющее тип функции. За исключением случаев, когда это операнд оператора sizeof или унарного оператора&, обозначение функции с типом " функция возвращаемый тип "преобразуется в выражение с типом " указатель на возвращаемый тип функции".
оказывается, что в C/C++ оба funcname
и &funcname
даст адрес funcname
и может быть присвоена переменной указателя функции. На самом деле это просто странность того, как синтаксис был разработан для языка(языков).
как и C, C++ имеет указатель на функции: указатель на функцию, которая не принимает аргументов и не возвращает значения. Однако C++ также ввел ссылки на функции void (&)()
и между ними есть неявные преобразования (хотя я точно не помню правила).
таким образом:
-
funcname
является ссылкой на функцию -
&funcname
- указатель на функцию
обратите внимание, что принимать адрес (или ссылка на) перегруженной функции требует static_cast
к точному типу (разрешить перегрузку).