1

我需要编写一个将“n”元素数组写入二进制输出文件的函数。我想避免为我可能希望编写的每种类型的数据(int、float、double 等)编写单独的函数。

有什么方法可以将数据类型(可能是字节数)指定为函数的参数,并让函数确定它如何处理它?

例如

f_writebinary(??? *data, int size, long n) {

   for(i=0;i<n;i++) {

        fwrite((data+i),size,1,stdout); 

    }
}

...或者这对 C 来说是一件完全荒谬的事情吗?

4

2 回答 2

2

是的,就是这样fwrite()。它使用 aconst void *表示“指向任何类型数据的指针”,并将其视为指向字节的指针。

因此,您的包装器并不是真正需要的,您可以立即进行正确大小的调用fwrite()来写入数组:

const int my_ints[3] = { 1, 2, 3 };
const double my_doubles[5] = { 5, 4, 3, 2, 1 };

fwrite(my_ints, sizeof *my_ints, sizeof my_ints / sizeof *my_ints, stdout);
fwrite(my_doubles, sizeof *my_doubles, sizeof my_doubles / sizeof *my_doubles, stdout);

请注意,写入二进制数据stdout可能有些粗鲁,而且应该检查 I/O 调用是否有错误。

如果您删除 API 使用的“y 字节的 x 元素”模型,fwrite()并将它们视为单个字节块,则可以简化调用:

fwrite(my_ints, sizeof my_ints, 1, stdout);
fwrite(my_doubles, sizeof my_doubles, 1, stdout);

请注意,循环没有意义,每个数组中的数字将在内存中相邻,因此fwrite()可以一次将它们全部写入。通常最好尽可能减少 I/O 调用的数量,因此如果您可以执行一次字节写入n * m而不是每次n写入m字节,那通常会更好。请记住,您写入的许多底层设备都是面向块的,并且将从获取整个数据块中受益匪浅,因为无论如何这是他们必须编写的。

于 2013-06-07T10:13:14.637 回答
1

只需替换???char. 或者在函数内部使用voidand cast to ,所以调用函数时char*不需要强制转换 to 。char*并且更好地使用size_t而不是intand long

#include <stdio.h>
...

size_t f_writebinary(void * data, size_t size, size_t n) 
{
  size_t result = 0;

  for (size_t i = 0; i < n; ++i) 
  {    
    size_t result_inner = fwrite(((char *) data) + (i * size), size, 1, stdout); 
    if (!result_inner)
    {
      /* handle error here */
    }
    else
    {
      ++result;
    }
  }

  return result;
}

优化版:

size_t f_writebinary(void * data, size_t size, size_t n) 
{
  size_t result = 0;

  n *= size;
  for (size_t i = 0; i < n; i += size) 
  {    
    size_t result_inner = fwrite(((char *) data) + i, size, 1, stdout); 
    if (!result_inner)
    {
      /* handle error here */
    }
    else
    {
      ++result;
    }
  }

  return result;
}

简而言之:只是模仿签名fwrite()使用。

于 2013-06-07T10:32:06.643 回答