如果传入的函数有参数,如何屏蔽来自 makecontext 的警告?
How can I mask the warning from makecontext if the function passed in has parameters?
在 C 语言 <ucontext_t.h>
中使用函数 makecontext
时,它采用参数 (ucontext_t* context, void (*someFunction)(void), int numberOfArguments, ...)
。 numberOfArguments
是传参给someFunction
,但是传参时编译报错
我需要或者应该删除这些,因为这是针对学校项目的,警告可能会让我失分。我想我可以编辑 Makefile 的标志,但我更愿意调整代码。
我做了 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:传递了一个整数作为参数
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
参数someFunction
的类型为void(*)(void)
,需要传递一个指向不带参数的函数的指针和returns void
(不是void *
)
您可以安排它工作,将 someFunction
的定义更改为如下内容:
void *(*someFunction)() /* don't specify the argument list */
在这种情况下,编译器将接受任何 returns void *
的函数,但是您必须仔细检查您传递的函数是否具有正确的参数数量和类型。这被称为不完整的类型定义,它很容易出错(它是从古老的 C 中保存下来的,在 ANSI 修订版之前很久)
如果您想要一个接受 void *
参数和 returns 一个 void *
结果的函数,请将 someFunction
的定义更改为:
void *(*someFunction)(void *), ...
但如果这是一个学术练习,我建议你做完整的类型检查,不要试图使用 C 工具来犯错误:)(他们要求你非常清楚你在做什么)
在你的例子中,辅助函数需要一个 int
参数,它不是 void *
(实际上,它们很可能大小不一样)所以 makecontext
函数将无法正确调用它。编译器在那里保护你免受你自己的伤害。
这实际上是makecontext()的这个manual指出的一个错误:
With the incorporation of the ISO/IEC 9899:1999 standard into this specification it was found that the ISO C standard (Subclause 6.11.6) specifies that the use of function declarators with empty parentheses is an obsolescent feature. Therefore, using the function prototype:
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
is making use of an obsolescent feature of the ISO C standard. Therefore, a strictly conforming POSIX application cannot use this form. Therefore, use of getcontext(), makecontext(), and swapcontext() is marked obsolescent.
通常的解决方法是使用强制转换。为此,定义一个新类型:
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("%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, (ucfunc_t)helper, 2, selectFunction, selectArg);
// Swap to context that calls function helper
swapcontext(&c0, &c1);
printf("Welcome back\n");
return 0;
}
在 C 语言 <ucontext_t.h>
中使用函数 makecontext
时,它采用参数 (ucontext_t* context, void (*someFunction)(void), int numberOfArguments, ...)
。 numberOfArguments
是传参给someFunction
,但是传参时编译报错
我需要或者应该删除这些,因为这是针对学校项目的,警告可能会让我失分。我想我可以编辑 Makefile 的标志,但我更愿意调整代码。
我做了 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:传递了一个整数作为参数
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
参数someFunction
的类型为void(*)(void)
,需要传递一个指向不带参数的函数的指针和returns void
(不是void *
)
您可以安排它工作,将 someFunction
的定义更改为如下内容:
void *(*someFunction)() /* don't specify the argument list */
在这种情况下,编译器将接受任何 returns void *
的函数,但是您必须仔细检查您传递的函数是否具有正确的参数数量和类型。这被称为不完整的类型定义,它很容易出错(它是从古老的 C 中保存下来的,在 ANSI 修订版之前很久)
如果您想要一个接受 void *
参数和 returns 一个 void *
结果的函数,请将 someFunction
的定义更改为:
void *(*someFunction)(void *), ...
但如果这是一个学术练习,我建议你做完整的类型检查,不要试图使用 C 工具来犯错误:)(他们要求你非常清楚你在做什么)
在你的例子中,辅助函数需要一个 int
参数,它不是 void *
(实际上,它们很可能大小不一样)所以 makecontext
函数将无法正确调用它。编译器在那里保护你免受你自己的伤害。
这实际上是makecontext()的这个manual指出的一个错误:
With the incorporation of the ISO/IEC 9899:1999 standard into this specification it was found that the ISO C standard (Subclause 6.11.6) specifies that the use of function declarators with empty parentheses is an obsolescent feature. Therefore, using the function prototype:
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
is making use of an obsolescent feature of the ISO C standard. Therefore, a strictly conforming POSIX application cannot use this form. Therefore, use of getcontext(), makecontext(), and swapcontext() is marked obsolescent.
通常的解决方法是使用强制转换。为此,定义一个新类型:
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("%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, (ucfunc_t)helper, 2, selectFunction, selectArg);
// Swap to context that calls function helper
swapcontext(&c0, &c1);
printf("Welcome back\n");
return 0;
}