Скажем, у меня есть указатель на функцию theFunc. theFunc берет с собой указатель, указывающий на адрес, где хранится theFunc. Это возможно?
Использование будет выглядеть так:
funcPtr(funcPtr);
Это вызывает функцию, на которую указывает funcPtr, а затем передает адрес указателя. Я не хочу использовать пустые указатели, потому что хочу изменить функцию, на которую указывает funcPtr.
Компилятору C/C++ нужно знать его размер, чтобы он мог генерировать правильные смещения.
@ADBeveridge, ваше последнее редактирование фактически изменило вопрос. В Stackoverflow вы не должны менять вопрос после того, как есть несколько действительных ответов. Пожалуйста, вернитесь к исходному вопросу и опубликуйте новый. См. здесь: meta.stackoverflow.com/questions/290297/….
@ADBeveridge Все указатели функций имеют одинаковый размер. Указатель функции void (как в 'void(*)(void)') не должен быть проблемой.
@wohlstad, мой новый вопрос опубликован здесь
@ADBeveridge спасибо. Я видел, что у тебя тоже есть ответы. Надеюсь, они помогут.





Вы не можете просто определить тип функции, которая принимает себя в качестве параметра. т.е. что-то вроде этого не будет работать:
/* Will cause a compilation error, MyFuncType used a parameter is not yet defined: */
typedef void(*MyFuncType)(MyFuncType);
Однако вы все равно можете использовать void* для достижения желаемого.
В typedef используется void*, но внутри функции вы можете привести его к типу указателя на функцию, изменить его и вызвать.
Глянь сюда:
typedef void(*MyFuncType)(void*);
void f(void* pF)
{
if (pF)
{
MyFuncType ff = (MyFuncType)pF;
/* Change ff here if you need. */
/* Call it: */
ff(0);
}
}
int main()
{
f(f);
return 0;
}
Обновлять:
Следуя комментарию @JosephSible-ReinstateMonica ниже, я добавил решение 2-й. Он не включает приведение между указателями данных и функций, но требует еще одного typedef и приведения при вызове f с самим собой:
typedef void(*FuncType1)(void);
typedef void(*MyFuncType)(FuncType1);
void f(MyFuncType pF)
{
if (pF)
{
/* Change pF here if you need. */
/* Call it: */
pF(0);
}
}
int main()
{
f((MyFuncType)f);
return 0;
}
Нет никакой гарантии, что вы сможете безопасно преобразовать указатель на функцию в указатель на данные. Вероятно, вы хотели написать что-то вроде typedef void(*MyFuncType)(void(*)(void));, а затем аналогичным образом настроить f.
@JosephSible-ReinstateMonica, но если я изменю MyFuncType, как вы предложили, и изменю f так: void f(void(*pF)(void)) я больше не смогу использовать f(f), чтобы вызывать его сам по себе. Я понимаю, что преобразование указателя данных в указатель на функцию может вызвать проблемы, но это единственный способ заставить его работать (пока я передаю действительную функцию в качестве аргумента). Пожалуйста, покажите, как это можно сделать, если я вас неправильно понял.
Разве вы не можете просто добавить дополнительный актерский состав, чтобы заставить его работать?
@JosephSible-ReinstateMonica Я обновил свой ответ вторым решением после ваших комментариев.
Да. Это возможно. C поддерживает неполные типы функций в виде функций, объявленных без прототипов. Например:
int fun();
Объявляет функцию, которая принимает неопределенное количество аргументов и возвращает int. Это позволяет определить каскад типов функций, приближающихся к желаемому типу функции, который принимает указатель на себя в качестве первого аргумента. Желаемый тип достигается на бесконечности, но для практической безопасности типов достаточно 2-3 уровней.
Например, приведенный ниже код компилируется без предупреждения даже в педантичном режиме.
int foo(int(int()));
int main(void) {
int (*fptr)(int(int())) = foo;
return fptr(fptr);
}
theFunctakes along a pointer that points to the address wheretheFuncis stored . Is this possible?
Да, это возможно, но это также 100% бессмысленно. Это похоже на то, как адресовать письмо самому себе, записывая в письме свой почтовый адрес. Вы идете, чтобы поместить это письмо в свой почтовый ящик, в то время как вы уже находитесь по этому физическому адресу, указанному в письме. Это не имеет никакого смысла — вы уже знаете адрес, поскольку вы уже там, так зачем вообще писать письмо? Правило № 1 в разработке программы: не делайте действительно странных вещей только потому, что можете.
Любое имя функции в C может превратиться в указатель на функцию при использовании в выражении. Таким образом:
void theFunc (void)
{
uintptr_t address = (uintptr_t)theFunc;
}
Нет необходимости в каких-либо параметрах.
Почему использование указателя void может быть проблемой?