Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果传入的函数具有参数,如何屏蔽makecontext中的警告?_C_Gcc_Casting_Ucontext - Fatal编程技术网

如果传入的函数具有参数,如何屏蔽makecontext中的警告?

如果传入的函数具有参数,如何屏蔽makecontext中的警告?,c,gcc,casting,ucontext,C,Gcc,Casting,Ucontext,在C语言中使用中的函数makecontext时,它接受参数(ucontext\u t*context,void(*someFunction)(void),int numberOfArguments,…)。numberOfArguments是将参数传递到someFunction,但是当传递参数时,我会收到编译警告 我需要,或者应该,删除这些,因为这是一个学校项目,警告可能会让我失去分数。我想我可以编辑Makefile的标志,但是我更愿意调整代码 我做了两次测试 1:将函数和字符串作为参数传递 te

在C语言中使用
中的函数
makecontext
时,它接受参数
(ucontext\u t*context,void(*someFunction)(void),int numberOfArguments,…)
numberOfArguments
是将参数传递到
someFunction
,但是当传递参数时,我会收到编译警告

我需要,或者应该,删除这些,因为这是一个学校项目,警告可能会让我失去分数。我想我可以编辑Makefile的标志,但是我更愿意调整代码

我做了两次测试

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;
}
$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;
}
$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

参数
someFunction
的类型为
void(*)(void)
,需要传递一个指向不带参数并返回
void
(非
void*
)的函数的指针

您可以安排它工作,将
someFunction
的定义更改为:

void *(*someFunction)()  /* don't specify the argument list */
在这种情况下,编译器将接受任何返回
void*
的函数,但是您必须再次检查您传递的函数是否具有正确数量和类型的参数。这被称为不完整的类型定义,并且非常容易出错(它是从远古的C保存下来的,早在ANSI修订版之前很久)

如果希望函数采用
void*
参数并返回
void*
结果,请将
someFunction
的定义更改为:

void *(*someFunction)(void *), ...
但是,如果这是一个学术练习,我建议您进行完整的类型检查,不要试图使用C工具来犯错误:)(它们要求您非常清楚自己在做什么)


在您的例子中,helper函数需要一个
int
参数,该参数不是
void*
(事实上,它们很可能大小都不一样),因此
makecontext
函数的主体将无法正确调用它。编译器在那里是为了保护您自己。

参数
someFunction
的类型为
void(*)(void)
,它需要传递一个指向不带参数并返回
void
(而不是
void*
)的函数的指针

您可以安排它工作,将
someFunction
的定义更改为:

void *(*someFunction)()  /* don't specify the argument list */
在这种情况下,编译器将接受任何返回
void*
的函数,但是您必须再次检查您传递的函数是否具有正确数量和类型的参数。这被称为不完整的类型定义,并且非常容易出错(它是从远古的C保存下来的,早在ANSI修订版之前很久)

如果希望函数采用
void*
参数并返回
void*
结果,请将
someFunction
的定义更改为:

void *(*someFunction)(void *), ...
但是,如果这是一个学术练习,我建议您进行完整的类型检查,不要试图使用C工具来犯错误:)(它们要求您非常清楚自己在做什么)


在您的例子中,helper函数需要一个
int
参数,该参数不是
void*
(事实上,它们很可能大小都不一样),因此
makecontext
函数的主体将无法正确调用它。编译器是为了保护您免受自己的伤害。

这实际上是makecontext()中指出的一个错误:

将ISO/IEC 9899:1999标准纳入本规范后,发现ISO C标准(第6.11.6款)规定使用带空括号的函数声明器是一种过时的特性。因此,使用功能原型:

void makecontext(ucontext\u t*ucp,void(*func)(),int argc,…)

正在利用ISO C标准的过时特征。因此,严格符合POSIX标准的应用程序不能使用此表单。因此,getcontext()、makecontext()和swapcontext()的使用被标记为过时

通常的解决方法是使用强制转换。要创建新类型,请定义一个新类型:

typedef void(*ucfunc_t)(void);
然后使用此定义强制转换传递给makecontext()的参数:

#包括
#包括
类型定义无效(*ucfunc_t)(无效);
//以字符串形式输出arg
void*f(void*arg){
printf(“%s\n”,(char*)arg);
返回0;//返回到c0
}
//makecontext接受argument2,(void(*)(void)),但允许(void(*)(…)
//我想从使用(void(*)(…)中删除警告
void助手(void*(*selectFunction)(void*),void*selectArg){
//使用select参数调用select函数
selectFunction(selectArg);
}
int main()
{
//初始化上下文
ucontext_t c0,c1;
字符堆栈[1024];
getcontext(&c1);
//c1的设置堆栈
c1.uc_stack.ss_sp=stack;
c1.uc_stack.ss_size=sizeof(stack);
c1.uc_link=&c0;//交换到c1堆栈端的c0堆栈
void*(*selectFunction)(void*)=&f;
void*selectArg=(void*)(“abc123测试”);
//将带有参数“abc123测试”的函数f传递给助手
makecontext(&c1,(ucfunc\u t)helper,2,selectFunction,selectArg);
//切换到调用函数帮助器的上下文
swapcontext(c0和c1);
printf(“欢迎回来”\n);
返回0;
}

这实际上是makecontext()中指出的一个错误:

将ISO/IEC 9899:1999标准纳入本规范后,发现ISO C标准(第6.11.6款)规定使用带空括号的函数声明器是一种过时的特性。因此,使用功能原型:

void makecontext(ucontext\u t*ucp,void(*func)(),int argc,…)

正在利用ISO C标准的过时特征