C Указатели на функции - Что происходит, когда вы отбрасываете аргумент? - PullRequest
1 голос
/ 27 марта 2011

все. В настоящее время я работаю со старой установленной базой кода для нового проекта, который в основном недокументирован (т.е. в среднем по 1 однострочному комментарию на файл). Я просто столкнулся с чем-то, чего раньше не видел, и не совсем уверен, как его интерпретировать.

Во-первых, они определяют тип функции и функцию в заголовочном файле (.h) в форме:


typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);

В основном исходном файле (.c) определена функция:


void add_function(void (*f)(void *data), void *data) 
{
   (Some code here)
}

Так, хорошо, есть указатель на функцию ... но что, черт возьми, случилось со вторым аргументом, ec? Зачем кому-то использовать такой дизайн кода? Для справки, когда используется функция add_function, она используется в такой форме:


void passedFunction(void *data, EXECUTION_CONTEXT *ec) 
{
    (Stuff the function does.)
}

void CallingFunction()
{
    data = (some data stuff);
    add_function((SOME_FUNCTION)passedFunction, data);
}

Итак, как вы можете видеть, переданные функции используют правильную форму, которая соответствует исходной сигнатуре аргумента SOME_FUNCTION, но определение для аргументов add_function является коротким на один аргумент.

Ответы [ 3 ]

3 голосов
/ 27 марта 2011

Чтобы добавить ответ Джеймса:

Поскольку соглашение о вызовах по умолчанию наиболее вероятно cdecl, сайт вызова отвечает за очистку стека после возврата passedFunction. Так как сайт вызова знает, что он передал вызываемому только 1 аргумент, компилятор может очистить стек нормально (даже если технически это неопределенное поведение).

Измените соглашение о вызовах на passedFunction на stdcall, и вы готовы к фейерверку.

3 голосов
/ 27 марта 2011

Формально результаты не определены: вам разрешается вызывать функцию только через указатель на функцию, если типы совпадают.

Что касается того, что на самом деле происходит, зависит от соглашения о вызовах и от того, что делает функцияс аргументами.Скорее всего, результаты не будут хорошими.

2 голосов
/ 27 марта 2011

Из приведенного ниже примера кода не видно, что переменные, которые определены в указателе функции, имеют значение во время проверки. Код ниже компилируется без предупреждения.

#include <stdio.h>

int temp(int (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(int (*m)()) {
        return 1;
}

Однако код ниже выдает ошибку.

#include <stdio.h>

int temp(void (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(void (*m)()) {
        return 1;
}

В связи с этим; кажется, что компилятор (по крайней мере, в моем случае GCC) заботится только о том, каким будет возвращаемое значение указателя функции. Интересно, что вы МОЖЕТЕ отправить параметры правильно, но если вы НЕ укажете параметр (в нашем примере m ()), то переменные в m () при вызове будут ненужными.

...