从空格中获取一个浮点数*

时间:2017-12-20 09:57:08

标签: c pointers variable-assignment

我正在尝试重新编程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()之类的命令,这是本练习的规则,所以不要告诉我解决方案隐藏在这里。

5 个答案:

答案 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