1

如何在 C 中的数组上定义通用映射操作?

理想情况下,我想要像 python 的 map(function,array) ~~ 但是作为一个宏。我相信这将类似于 C++ 的 std::transform,但会在 C 中,并且不使用迭代器。

(这将是一元操作)我在想这样的事情:

template <class T*, class U*,size_t N>
T* map(T (*func)(U), U* arr,size_t N)
{
   T* tmp = (T*)malloc(sizeof(T) * N);
   size_t i;
   for(i=0;i<N;i++)
   {
       *(tmp+i) = *func(*(arr+i));
   }
}

...但当然模板是 C++ 中的..所以我怎么能 1)做后者和 2)如果可以的话,你能修复上面的代码片段吗?

谢谢

4

2 回答 2

1

对于这样的模板,有一个相当简单的宏转换;主要的语法问题是你不能返回结果数组,写入它的变量必须是另一个参数。

#define map(func_, input_, output_, type_, n_) do { \
    output_ = xmalloc(sizeof(type_) * (n_));        \
    size_t i_;                                      \
    for (i_ = 0; i_ < (n_); i_++)                   \
        output_[i_] = func_(input_[i_]);            \
  } while (0)

如果您注意编译器警告,这并不像看起来那样类型不安全。但是,如果使用此宏的任何实际参数不是简单的标识符,则不是特别安全。最重要的是,如果任何实际参数有副作用,就会发生灾难性的事情。

这可以解决,无法返回结果数组也可以解决,但前提是您愿意使用 GNU 扩展...

#define gnumap(func_, input_, type_, n_) ({                    \
    __typeof(func_)   func__   = (func_);                      \
    __typeof(input_)  input__  = (input_),                     \
                      output__ = xmalloc(sizeof(type_) * n__); \
    __typeof(n_)      n__      = (n_),                         \
                      i__;                                     \
    for (i__ = 0; i__ < n__; i__++)                            \
        output__[i__] = func__(input__[i__]);                  \
    /* return */ output__;                                     \
  })

我会在现实生活中做这些吗?可能不是,但有时它确实是最糟糕的可用选项。把它想象成比用汇编语言重写那个关键的内部循环还差一步。

xmalloc如果您不熟悉它,它是用户编写的包装器的常规名称,malloc它要么成功要么使整个程序崩溃。我在这里使用它来回避如何应对malloc失败的问题。)

于 2013-02-08T23:41:12.953 回答
0

因此,您可以编写一个函数,该函数接受一个函数指针和一个void *(或char *)数据,以及一个数据大小。

我当然不会只使用宏来执行此操作,但您可能有一个宏可以执行以下操作:

 #define MAP(func, type, arr, size) map(func, sizeof(type), arr, size)

并且map是我上面描述的功能。

于 2013-02-08T23:32:28.700 回答