Приведение типа указателя на функцию

Я знаю, что это дубликат. Я уже искал, но никто не решает проблему, с которой я сталкиваюсь. ПРИМЕЧАНИЕ в попытке устранить мою путаницу я попытался упростить приведение типа к оригиналу. Надеюсь, это не неопределенное поведение

Объявление указателя на функцию

Int (*funcPtr)(void*,void*);

декларация strcmp

int strcmp (char *, char *);

Приведение типа указателя на функцию

FuncPtr = (int (*)(void*, void*))strcmp

Вот тут я запутался. Я понимаю преобразование типа указателя функции, который мы создали. Например, приведение типа FuncPtr просто меняет тип функции, на которую может указывать funcPtr. Я также читал, что имя функции является указателем функции на себя, поэтому приведение типов strcmp и использование моего понимания выше,

int (*)(void*, void*))strcmp 

Strcmp теперь может указывать на функцию, которая принимает два указателя на void и возвращает int, что явно неверно, как и массивы. Я думаю, что имя функции не может быть указателем на другую функцию.

Из-за моего понимания выше я не вижу, как вы можете назначить адрес strcmp для FuncPtr со следующим приведением типа

FuncPtr = (int (*)(void*, void*))strcmp

Поскольку изменение того, на что указывает указатель функции strcmp, не меняет аргументы и тип возвращаемого значения strcmp.

Я был бы очень признателен за некоторые знания, я просто так запутался.


person Simple    schedule 08.05.2017    source источник
comment
Ну, то, что ты можешь, не означает, что это хорошая идея. Я могу врезаться на машине в дерево, если захочу, но...   -  person ThingyWotsit    schedule 08.05.2017
comment
Любой указатель функции может указывать на любую функцию, но вам не разрешено вызывать функцию через указатель, если тип, на который указывает, точно не соответствует функции, на которую указывает указатель.   -  person M.M    schedule 08.05.2017
comment
Я думаю, что имя функции не может быть указателем на другую функцию, а? Что ты вообще здесь имеешь в виду? А что такое FuncPtr, какого типа? Обратите внимание, что язык C чувствителен к регистру.   -  person Lundin    schedule 08.05.2017
comment
Если вопрос просто в том, могу ли я иметь указатель функции типа int (*)(void*, void*)), а затем привести адрес strcmp к этому типу? то я могу ответить на него. Однако все остальное в вашем вопросе делает его неясным. Также для записи, strcmp имеет следующий формат, который здесь имеет значение: int strcmp(const char *s1, const char *s2);.   -  person Lundin    schedule 08.05.2017
comment
Я имею в виду, что под преобразованием типа strcmp изменяет то, на что указывает strcmp. Однако я не думаю, что можно изменить то, на что указывает strcmp.   -  person Simple    schedule 08.05.2017
comment
Проще говоря Funcptr = (int ()(void, void*))strcmp   -  person Simple    schedule 08.05.2017
comment
Проще говоря, Funcptr = (int ()(void, void*))strcmp логически эквивалентен Funcptr = strcmp для меня, потому что я не вижу, как преобразование типа strcmp изменяет аргументы и возвращаемый тип strcmp для соответствия что из Funcptr для назначения   -  person Simple    schedule 08.05.2017
comment
@M.M, это должно точно совпадать? Или я могу вызвать int(*foo)(int, int), используя int (*foo) (int, ...); (конечно, с двумя аргументами, а второй тоже int). Я видел это много.   -  person Ajay Brahmakshatriya    schedule 08.05.2017
comment
Нет, мне все равно   -  person Simple    schedule 08.05.2017
comment
@AjayBrahmakshatriya Параметры должны точно совпадать. Некоторые системы могут использовать нестандартные расширения для указателей функций. Это также распространенное нестандартное расширение, позволяющее преобразовать указатели функций в void*.   -  person Lundin    schedule 08.05.2017
comment
@AjayBrahmakshatriya в Standard C должно быть точным совпадением. Все остальное нестандартные расширения   -  person M.M    schedule 08.05.2017


Ответы (1)


Есть функции и есть указатели на функции. strcmp — это функция, связанная с вашим проектом. Когда идентификатор strcmp используется в выражении, вы получаете указатель на эту функцию. Но вы не можете изменить «куда указывает strcmp», потому что strcmp — это функция, а не указатель.

C позволяет выполнять преобразования между различными типами указателей функций. Однако если вы попытаетесь вызвать функцию с помощью указателя функции несовместимого типа, вы вызовете неопределенное поведение.

int (*funcPtr)(void*,void*);

не совместим с strcmp, который имеет следующий формат:

int strcmp(const char *s1, const char *s2);

Значение:

funcPtr = (int(*)(void*, void*))strcmp; // this is ok but not very meaningful
funcPtr(); // this is NOT ok, invokes undefined behavior

Чтобы на самом деле вызвать функцию strcmp с помощью этого указателя функции, вам нужно будет вернуться к правильному типу, который является int (*)(const char*, const char*).

person Lundin    schedule 08.05.2017
comment
Имя функции (метка) преобразуется в указатель на себя. denniskubes.com/2013/03/22/basics -of-function-pointers-in-c в последней главе обсуждается это - person Simple; 08.05.2017
comment
Я все еще не понимаю, что делает приведение (int()(void, void*) к strcmp? Изменяет ли оно тип аргумента на void и возвращает тип на int - person Simple; 08.05.2017
comment
@Simple Это ничего не делает для strcmp по той же причине, что и int x=0; char* ptr = &x; ничего не делает для x. Указатель содержит адрес указанного элемента. Просто потому, что вы позволяете указателю другого типа указывать на вашу переменную, это не меняет тип самой переменной. - person Lundin; 08.05.2017