Можно ли вызвать статическую функцию через указатель на функцию в языке Си?


Я считаю, что статическая функция в исходном файле не может быть вызвана непосредственно из-за пределов файла. Однако, если мне каким-то образом удастся получить указатель на эту функцию в другой файл, я могу вызвать эту функцию из этого файла. Если да, то есть ли какой-либо сценарий, когда мы хотели бы пойти этим путем по сравнению с простым созданием функции нестатической ?

7 26

7 ответов:

Да, вы можете экспортировать статические функции, выдавая на них указатели. Это распространенное средство реализации фабричного шаблона В C, где можно скрыть реализации целого набора функций от модулей, которые их используют, и иметь FuncPtr_t GetFunction( enum whichFunctionIWant), который раздает их потребителям. Именно так работает множество реализацийдинамического связывания .

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

Да, это вполне возможно. Функция не видна компоновщику, но она есть в исполняемом файле. Вы всегда можете перейти по его адресу.

Хотя я не уверен в сценариях. Может быть, вы хотите, чтобы другие вызывали только вашу функцию после того, как они вызвали какую-то другую функцию (нестатическую, конечно). Так что они у вас есть получить его, а затем они могут вызвать его.

Как уже упоминалось, вы можете это сделать. Пример того, почему вы можете захотеть, - это для какого-то"водителя". Вы можете передать обратно структуру, содержащую функции open, close, read и write, не делая их общедоступными.

Да, нестатическая функция в вашем файле может возвращать указатель на статическую функцию в любое место.

Да, можешь. Если необходимо вызвать функцию, которая ожидает указатель на функцию в качестве обратного вызова, можно использовать статический метод, чтобы символ функции не загрязнял глобальное пространство имен и не вызывал конфликтов компоновщика. Наиболее часто используемый пример, вероятно, qsort:

struct Data { ... };

static int compareData(const void* a, const void* b) { /* cast to Data and compare */ }

...
qsort(array, count, sizeof(Data), &compareData);

Часто бывает полезно определить небольшую статическую функцию как рабочую функцию для какой-то другой. Посмотрите на стандарт qsort для примера: он ожидает функцию сравнения, и очень часто лучше сделать эту функцию сравнения статической (например, потому, что она не полезна в другом месте, и потому, что qsort хочет, чтобы она имела некоторую непреттированную подпись).

Да, вы можете, вы всегда можете попробовать это для себя и узнать:

файл 1.c

#include <stdio.h>

void call_hello(void (*fptr)(void));

static void hello(void) {
   puts("hello");
}

int main(void)
{
   void (*fptr)(void) = hello;

   call_hello(fptr);

   return 0;
}

файл 2.c

void call_hello(void (*fptr)(void))
{
   fptr();
}