Как я могу замаскировать предупреждение от makecontext, если переданная функция имеет параметры? - PullRequest
0 голосов
/ 08 марта 2020

При использовании функции makecontext из <ucontext_t.h> в C она принимает аргументы (ucontext_t* context, void (*someFunction)(void), int numberOfArguments, ...). numberOfArguments должен передавать аргументы в someFunction, но при передаче аргументов я получаю предупреждения компиляции.

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

Я сделал 2 теста.

1 : пройдено функция и строка в качестве аргументов

Код для test1:

#include <stdio.h>
#include <ucontext.h>

// Outputs arg as a string
void* f(void* arg) {
    printf("%s\n", (char*)arg);
    return 0; // Returns back to c0
}

// makecontext takes as argument2, (void (*)(void)), but allows (void (*)(...))
// I want to remove the warning from using (void (*)(...))
void helper(void* (*selectFunction)(void*), void* selectArg) {
    // Calls select function with select argument
    selectFunction(selectArg);
}

int main()
{
    // Initialize contexts
    ucontext_t c0, c1;
    char stack[1024];

    getcontext(&c1);
    // Setup stack for c1
    c1.uc_stack.ss_sp = stack;
    c1.uc_stack.ss_size = sizeof(stack);
    c1.uc_link = &c0; // Swap to c0 stack on c1 stack end

    void* (*selectFunction)(void*) = &f;
    void* selectArg = (void*)("abc123 testing testing");

    // Passes function f with arg "abc123 testing testing" to helper
    makecontext(&c1, helper, 2, selectFunction, selectArg);

    // Swap to context that calls function helper
    swapcontext(&c0, &c1);

    printf("Welcome back\n");

    return 0;
}

Мой вывод для test1:

$gcc -o main *.c
main.c: In function ‘main’:
main.c:33:22: warning: passing argument 2 of ‘makecontext’ from incompatible pointer type [-Wincompatible-pointer-types]
     makecontext(&c1, helper, 2, selectFunction, selectArg);
                      ^~~~~~
In file included from main.c:2:0:
/usr/include/ucontext.h:47:13: note: expected ‘void (*)(void)’ but argument is of type ‘void (*)(void * (*)(void *), void *)’
 extern void makecontext (ucontext_t *__ucp, void (*__func) (void),
             ^~~~~~~~~~~
$main
abc123 testing testing
Welcome back

2 : Передал int в качестве аргумента

Код для test2:

#include <stdio.h>
#include <ucontext.h>

// Outputs arg as a string
void f(int n) {
    printf("%d\n", n);
    return; // Returns back to c0
}

// makecontext takes as argument2, (void (*)(void)), but allows (void (*)(...))
// I want to remove the warning from using (void (*)(...))
void helper(int arg) {
    // Calls f with arg
    f(arg);
}

int main()
{
    // Initialize contexts
    ucontext_t c0, c1;
    char stack[1024];

    getcontext(&c1);
    // Setup stack for c1
    c1.uc_stack.ss_sp = stack;
    c1.uc_stack.ss_size = sizeof(stack);
    c1.uc_link = &c0; // Swap to c0 stack on c1 stack end

    // Make a context to run f with argument 5
    makecontext(&c1, helper, 1, 5);

    // Swap to context that calls function helper
    swapcontext(&c0, &c1);

    printf("Welcome back\n");

    return 0;
}

Мой вывод для test2:

$gcc -o main *.c
main.c: In function ‘main’:
main.c:30:22: warning: passing argument 2 of ‘makecontext’ from incompatible pointer type [-Wincompatible-pointer-types]
     makecontext(&c1, helper, 1, 5);
                      ^~~~~~
In file included from main.c:2:0:
/usr/include/ucontext.h:47:13: note: expected ‘void (*)(void)’ but argument is of type ‘void (*)(int)’
 extern void makecontext (ucontext_t *__ucp, void (*__func) (void),
             ^~~~~~~~~~~
$main
5
Welcome back

1 Ответ

1 голос
/ 10 марта 2020

Параметр someFunction имеет тип void(*)(void), для которого требуется передать указатель на функцию, которая не принимает аргументов и возвращает void (не void *)

Вы можете организовать чтобы это работало, изменив определение someFunction на что-то вроде:

void *(*someFunction)()  /* don't specify the argument list */

В этом случае компилятор примет любую функцию, которая возвращает void *, но затем вы должны дважды проверить, что функция у вас есть правильное количество и типы аргументов. Это называется неполным определением типа, и оно очень подвержено ошибкам (оно сохраняется с древних C, задолго до пересмотра ANSI)

, если вы хотите функцию, которая принимает аргумент void * и возвращает результат void *, измените определение someFunction на:

void *(*someFunction)(void *), ...

Но если это академическое упражнение c, я предлагаю вам выполнить полную проверку типа и не пытаться использовать средства C для совершения ошибок :) (они требуют, чтобы вы хорошо знали, что делаете)

В вашем случае вспомогательная функция требует параметра int, который не является void * (действительно, скорее всего, они даже не имеют одинаковый размер), поэтому тело функции makecontext не сможет вызвать ее правильно. Компилятор защищает вас от вас.

...