我怎么做以下的通用功能,用于uint8_t,uint16_t,uint32_t,int8_t,int16_t,int32_t和float_t?

我不喜欢重复同样的逻辑,在每种情况下你可以看到。唯一的区别在每一种情况是铸造。

我想像的解决方案,遵守C范和标准,因此便携式。任何想法都值得欢迎的。

谢谢。

static bool_t IsWithinLimits(const dbKey_t *key, const void *data)
{
    bool_t isWithinLimits = TRUE;
    limits_t limits = getDefinedLimits(key);

    switch(key->type)
    {
      case TYPE_UINT8:
        if((*(const UINT8*)data > (UINT8)limits.max) || (*(const UINT8*)data < (UINT8)limits.min))
        {
          isWithinLimits = FALSE;
        }
        break;

      case TYPE_UINT16:
        if((*(UINT16*)pData > (UINT16)limits.max) || (*(UINT16*)data < (UINT16)limits.min))
        {
          isWithinLimits = FALSE;
        }
        break;

      case TYPE_UINT32:
       ...
       break;

      case TYPE_INT8:
       ...
       break;

      case TYPE_INT16:
       ...
       break;

      case TYPE_INT32:
       ...
       break;

      case TYPE_FLOAT:
       ...
       break;
    }

  return isWithinLimits;
}
有帮助吗?

解决方案

好吧,你 可能 提取石膏像:

int64_t loadptr_uint8(const void *p)  {
    return *(uint8_t*)p;
}
int64_t convert_uint8(int64_t val) {
    return (uint8_t)val;
}

int testLimits(const limits_t *plimits, const void *pData, int64_t(*loadptr)(void*), int64_t (*convert)(int64_t)) {
    return loadptr(pData) <= convert(limits->max) && loadptr(pData) >= convert(limits->min);
}

switch(key->type) {
    case TYPE_UINT8:
        isWithinLimits = testLimits(&limits, pData, loadptr_uint8, convert_uint8);
        break;
    // etc
}

或者,如果各种类型形成一个连续的数值范围从0,你甚至可以让两个阵列功能的指针和做:

bool isWithinLimits = testLimits(&limits, pData, loadptrs[key->type], converts[key->type]);

注:

  • 你还是要写的两个功能用于每种类型,虽然他们是轻松的宏观所产生的如果你喜欢。
  • 它并不真的似乎值得对这个小小的代码。
  • 我选择 int64_t 因为它是能够代表所有价值观的所有整数类型的使用,所以转换 int64_t 永远不会放弃信息和永远不会改变结果的比较相对于与做同样的比较在源类型。但如果你还想要掩盖 uint64_t, 然后你不能用同样类型的一切,因为没有整数类型,可以代表所有价值观的所有整类型。你还需要一个独立的 testLimitsf 功能 float, 也许使用 long double 作为常见的类型对未来的灵活性。
  • [编辑:我只是意识到,假如IEEE-754, double 实际上可以确切地代表的所有价值观的所有类型的使用。所以有轻微的可携带性限制,可以使用 testLimitsf 对于一切和处理在一倍]
  • 你确定这是值得转换,以(例如) uint8_t 之前的比较?值是在范围 uint8_t, ,在这种情况下你不需要转换,你可以做比较。或其他的价值不在范围内,在这种情况下模减少使得比较有点毫无意义,除非在特殊情况下的0和-1。所以它可能是值得的,如果有什么你没有指出,使得它如此,但是它看起来腥给我。
  • 你说的评论,"我正试图使这一职能更加高效"。这可能会去的反对。它的逻辑可能的内联 testLimits 并且还呼吁铸造的功能 switch, 但我不会依靠它。

其他提示

在C语言中,没有简单的方法可以进行这样的泛型编程。如果您担心维护,那么在这种情况下,适合使用宏的情况很少见。

为什么不使用宏? 通用标签

该标准的下一个修订版(C1x)将添加对类型通用表达式的支持(例如来自维基百科): 通用标签

gcc初步支持C1x。我认为_Generic尚不受支持,但请牢记未来。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top