我正在尝试设置一个函数数组,这些函数接受需要不同变量的函数(例如,
my_putchar
需要一个char
,而my_put_nbr
需要一个int
),所以我决定定义它使用 void *
。虽然它确实有效,但在编译时会发出警告。
#include "stdarg.h"
#include "my.h"
int put_perc(void)
{
my_putchar('%');
}
int read_print(const char *s, int i, va_list args)
{
int k = 0;
char guide[] = "cdis%f";
int (*functions[])(void *) = {my_putchar, my_put_nbr,
my_put_nbr, my_putstr, put_perc, my_put_float};
for (k = 0; s[i + 1] != guide[k]; k++);
functions[k](va_arg(args, void *));
}
void mini_printf(const char *s, ...)
{
int k = 0;
va_list args;
char guide[] = "cdis%";
va_start(args, s);
for (int i = 0; i < my_strlen(s); i++) {
if (s[i] == '%') {
read_print(s, i, args);
i++;
} else {
my_putchar(s[i]);
}
}
va_end(args);
}
void main(void)
{
mini_printf("%s %s %s letter is %c followed by %d and %i.\nfloats %f \nlets also test this out, %s 100%%\n", "come", "on", "WORK", 'h', 58, 12, 55.756567575658, "this should work");
}
这些是我收到的警告。
my_printf.c: In function ‘read_print’:
my_printf.c:20:35: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘void (*)(char)’ [-Wincompatible-pointer-types]
20 | int (*functions[])(void *) = {my_putchar, my_put_nbr,
| ^~~~~~~~~~
my_printf.c:20:35: note: (near initialization for ‘functions[0]’)
my_printf.c:20:47: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘int (*)(int)’ [-Wincompatible-pointer-types]
20 | int (*functions[])(void *) = {my_putchar, my_put_nbr,
| ^~~~~~~~~~
my_printf.c:20:47: note: (near initialization for ‘functions[1]’)
my_printf.c:21:9: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘int (*)(int)’ [-Wincompatible-pointer-types]
21 | my_put_nbr, my_putstr, put_perc, my_put_float};
| ^~~~~~~~~~
my_printf.c:21:9: note: (near initialization for ‘functions[2]’)
my_printf.c:21:21: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘int (*)(const char *)’ [-Wincompatible-pointer-types]
21 | my_put_nbr, my_putstr, put_perc, my_put_float};
| ^~~~~~~~~
my_printf.c:21:21: note: (near initialization for ‘functions[3]’)
my_printf.c:21:32: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘int (*)(void)’ [-Wincompatible-pointer-types]
21 | my_put_nbr, my_putstr, put_perc, my_put_float};
| ^~~~~~~~
my_printf.c:21:32: note: (near initialization for ‘functions[4]’)
my_printf.c:21:42: warning: initialization of ‘int (*)(void *)’ from incompatible pointer type ‘int (*)(double)’ [-Wincompatible-pointer-types]
21 | my_put_nbr, my_putstr, put_perc, my_put_float};
| ^~~~~~~~~~~~
my_printf.c:21:42: note: (near initialization for ‘functions[5]’)
我真的不知道如何解决这个问题,因为我只是认为
void *
充当了变量类型的包罗万象的角色。 (这只是我编码的第三周,所以我还没有那么有经验)
我只是认为 void * 充当了变量类型的包罗万象的角色。
不完全是,不。事实是,任何 pointer 类型都可以转换为
void *
并返回。 (请注意,回到原始指针类型。不仅仅是any指针类型。)
但是这里...
int (*functions[])(void *)
...是一个指向函数的指针数组,返回 int
并以
void *
作为参数。 然而,您的实际函数采用非指针类型(
char
、
int
、
void
、
double
)或const指针(
const char *
)。如果不进行强制转换,这些都无法转换为
void *
。那只是你麻烦的开始。例如,您的
put_perc
不接受任何争论。不过,您将调用作为带有参数的函数,将其传递给堆栈中的下一个
void *
...我看到您的这个构造将发生各种“有趣”的事情。我建议,不要调用
read_print
并期望它“自动运行”,而是阅读 中
'c'
后面的转换说明符(
's'
、
'd'
、
'%'
...)
mini_printf
格式,对其执行
switch
,并在相应的
case
中执行正确的操作,例如打印
'%'
或获取堆栈中的
int
并将其传递给
my_put_nbr
。这样就干净很多,很多。