我正在尝试重新编程printf函数(大学项目)但%f导致我出现问题。 我使用像这样的函数指针:
void (*fct[15])(void*) =
{printfs, printfc, printfd, printfd, printfl, printfx, printfX,
printfo, printfb, printfS, printfu, printfp, printff};
当使用右标志时,调用其中一个函数。 典型的printfd将收到一个void *变量作为参数,并将这样做:
int nbr = (int)var; //var is a void* type variable
my_put_nbr(var); //handmade function wich displays numbers
事情是,出于一些奇怪的原因,当我为printff做同样的事情时,它无法正常工作
float nbr = (float)var;
我收到了消息
错误:指向预期浮点值的指针值 float nbr =(float)var
我也尝试过这样的事情。如果我有
my_printf("%f", var); //with var = 12.34
然后我调用printff()函数:
int nbr1 = (int)(var / 1);
int nbr2 = (int)(var % 1);
所以我通常有nbr1 = 12和nbr2 = 34然后我会在'。'之间显示两者。但它仍然无法正常工作,我收到了消息:
错误:二进制*的无效操作数(有'void *'和'int')int nbr1 =(int)(var * 1)
我不在意,所以如果你有任何线索,请告诉我。 另外,我不能使用像printf()之类的命令,这是本练习的规则,所以不要告诉我解决方案隐藏在这里。
答案 0 :(得分:2)
如果我正确理解你的问题,当你完全确定调用者部分时,在被调用的函数中,考虑到你在var
中收到了参数,你可以做
int
printf("%d", *(int *)var);
适用于float
/ double
printf("%f", *(double *)var);
等等。
请注意,变量函数没有float
类型,因为对于这些函数,由于默认参数提升,float
类型会被提升为double
。
详细说明,您不会将传入指针强制转换/分配给所需类型(无效[类型不匹配]和不需要的类型)。相反,您将void *
参数转换为适当的调用者参数类型(基于您提到的标志),然后取消引用以获取该值。
这个类比是基于C11
中提到的属性,第6.3.2.3章
指向
void
的指针可以转换为指向任何对象类型的指针。指向的指针 任何对象类型都可以转换为指向void
并再次返回的指针;结果应该 比较等于原始指针。
答案 1 :(得分:1)
这叫做双关语。指针惩罚是UB。最安全的方法是将void指针中的数据memcpy到float变量。
float x;
memcpy (&x, voidptr, sizeof(float));
答案 2 :(得分:1)
您没有正确调用va_args
。第二个参数必须是您希望从变量参数读取的数据类型,因为va_args
需要正确的大小才能知道从哪里获取下一个参数。
虽然使用数组来存储所有可能的函数可能看起来很聪明,但实际上当你有一个更简单,更易读的方法时,你会更难为自己做事。它也可能更具扩展性。
switch(format_char)
{
case 'd':
print_an_int(va_args(args,int));
break;
case 'f':
print_an_float(va_args(args,float));
break;
}
答案 3 :(得分:0)
尝试使用
int nbr = *((int *)var);
float nbr = *((float *)var);
将void指针var转换为整数/浮点指针,然后获取存储在该内存地址中的值并将值存储到变量中
而不是
int nbr =(int)var;
float nbr =(float)var;
将存储在var中的地址转换为int / float。在这里,您只是转换地址而不是存储在该地址中的值。
答案 4 :(得分:0)
不是试图从args
中提取参数并将结果传递给fct[i]
,而是直接将args
传递给fct[i]
,让他们进行提取。唯一需要注意的是,你不能通过价值来传递。
fct[i](&args);
在每个printf *辅助函数中都执行以下操作:
void printf_double (va_list *args) {
double val = va_arg(*args, double);
// print it
}
注意float
不是printf
的有效类型,因为float
在varargs调用中被提升为double
。