如何为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;
}
4 回答
好吧,你可以提取演员表:
或者,如果各种类型从0形成一个连续的值范围,您甚至可以创建两个函数指针数组并执行:
笔记:
您仍然需要为每种类型编写两个函数,尽管如果您愿意,它们很容易被宏生成 .
对于这个小代码来说,这似乎并不值得 .
我选择
int64_t
,因为它能够表示您使用的所有整数类型的所有值,因此转换为int64_t
永远不会丢弃信息,并且永远不会更改比较的结果与在源中进行相同的比较类型 . 但是如果你还想覆盖uint64_t
,那么't use the same type for everything, since there is no integer type that can represent all the values of all integer types. You'还需要一个单独的testLimitsf
函数用于float
,可能使用long double
作为未来灵活性的通用类型 .[编辑:我刚刚意识到,假设IEEE-754,
double
实际上可以准确地代表您使用的所有类型的所有值 . 因此,轻微的可移植性限制,您可以使用testLimitsf
来处理所有事情并处理双打]您确定在比较之前转换为(例如)
uint8_t
是否值得?这个值在uint8_t
的范围内,在这种情况下你不在范围内,在这种情况下模数减少使得比较有点无意义,除了在0和-1的特殊情况下 . 所以它可能是值得的,如果你没有陈述的东西使它如此,但它看起来很可疑 .你在评论中说,"I am trying to make that function more efficient" . 这可能违背了这一点 . 在逻辑上可以内联
testLimits
以及switch
中对转换函数的调用,但我不会指望它 .标准的下一个版本(C1x)将添加对类型泛型表达式的支持(来自维基百科的示例):
gcc有一些初步的C1x支持 . 我认为_Generic尚未得到支持,但请记住未来 .
为什么不使用宏?
在C中没有简单的方法来执行这样的泛型编程 . 如果您担心维护,那么这可能是一个非常适合宏的场合 .