c-如果传入的函数有参数,我如何从makecontext屏蔽警告



使用C中<ucontext_t.h>的函数makecontext时,它接受参数(ucontext_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("%sn", (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 backn");
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("%dn", 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 backn");
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

参数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_t*ucp,void(*func(((,int argc,…(;

正在利用ISO C标准的一个过时功能。因此,严格符合POSIX的应用程序不能使用这种形式。因此,getcontext((、makecontext(((和swapcontext((的使用被标记为废弃。

通常的解决方法是使用强制转换。要做到这一点,请定义一种新类型:

typedef void (* ucfunc_t)(void);

然后使用此定义强制转换传递给makecontext((的参数:

#include <stdio.h>
#include <ucontext.h>
typedef void (* ucfunc_t)(void);
// Outputs arg as a string
void* f(void* arg) {
printf("%sn", (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, (ucfunc_t)helper, 2, selectFunction, selectArg);
// Swap to context that calls function helper
swapcontext(&c0, &c1);
printf("Welcome backn");
return 0;
}

相关内容

  • 没有找到相关文章

最新更新