13

是否有相当标准的 C (Linux) 函数或代码效率高但性能良好的方法来比较任意大小的两个整数?

我正在寻找具有int intcmp(const void *a, const void *b, size_t size)适用于整数ab任何实际大小的参数的东西size。(memcmp()如果架构是大端的,会工作(我认为)。)

我倾向于使用的实现是这样的(通过Efficient integer compare function的改进),但它不是完全通用的,并且有足够的代码开销,我通常在插入它之前会三思而后行。

int intcmp(const void *a, const void *b, size_t size) {

    #define CASE_SIZE_RETURN_A_B_CMP(_t) \
        case sizeof(_t): \
            return ((*(_t *)(a) > *(_t *)(b)) - (*(_t *)(a) < *(_t *)(b)))

    switch (size) {
    CASE_SIZE_RETURN_A_B_CMP(char);
    CASE_SIZE_RETURN_A_B_CMP(short);
    CASE_SIZE_RETURN_A_B_CMP(int);
    CASE_SIZE_RETURN_A_B_CMP(long long);
    }
    #undef CASE_SIZE_RETURN_A_B_CMP

    assert(0);
    return 0;
}
4

4 回答 4

2

静态内联函数的优点是参数只被评估一次(这对于宏来说很难/不可能)。这将允许函数调用,如int diff = cmp_all (p++, q++, sizeof *p);

#include <stdlib.h>
#include <stdint.h>

static inline int cmp1(const int8_t *one, const int8_t *two)
{
if (*one < *two) return -1;
else if (*one > *two) return 1;
else return 0;
}

static inline int cmp2(const int16_t *one, const int16_t *two)
{
if (*one < *two) return -1;
else if (*one > *two) return 1;
else return 0;
}

static inline int cmp4(const int32_t *one, const int32_t *two)
{
if (*one < *two) return -1;
else if (*one > *two) return 1;
else return 0;
}

static inline int cmp8(const int64_t *one, const int64_t *two)
{
if (*one < *two) return -1;
else if (*one > *two) return 1;
else return 0;
}

int cmp_all(const void *one, const void *two, size_t size)
{
switch(size) {
case 1: return cmp1(one, two);
case 2: return cmp2(one, two);
case 4: return cmp4(one, two);
case 8: return cmp8(one, two);
default: return 0; /* that will teach them ... */
        }
}
于 2013-05-26T10:18:04.907 回答
1

如果您确实需要对任意大小的整数进行良好的比较,我建议您查看The GNU Multiple Precision Arithmetic Library。这需要您使用它的特殊 mpz_t 类型(包括长度)。然后就可以使用该功能了int mpz_cmp(mpz_t op1, mpz_t op2)。决定你自己的大整数表示并以相当可移植和高效的方式实现它并非易事。

另一方面,如果您只需要您提到的标准整数大小,我认为您的实现很好。但是为了更好的可移植性,您不应该对各种整数大小做出假设:

#include <stdint.h>

int intcmp(const void *a, const void *b, size_t size) {
    switch (size) {
    case 1: return (*(int8_t*)a > *(int8_t*)b) - (*(int8_t*)a < *(int8_t*)b)
    case 2: return (*(int16_t*)a > *(int16_t*)b) - (*(int16_t*)a < *(int16_t*)b)
    case 4: return (*(int32_t*)a > *(int32_t*)b) - (*(int32_t*)a < *(int32_t*)b)
    case 8: return (*(int64_t*)a > *(int64_t*)b) - (*(int64_t*)a < *(int64_t*)b)
    }

    assert(0);
    return 0;
}

也许您会发现为所需的每个长度创建一个单独的函数而不是对所有长度都使用相同的函数会更好?最后,如果效率很重要,使用charshort进行算术运算的效率通常低于使用int的效率。因此,请尽量避免需要使用 char 或 short 调用此函数并改用 int 的情况。

于 2013-05-26T05:53:18.230 回答
0

如果调用站点有可用的大小,我更愿意将它用作那里的查找表中的索引,以便立即调用正确的函数。

于 2013-05-13T15:00:58.387 回答
0

我认为以下链接会有所帮助。您可以在不使用比较器的情况下进行比较,从而降低代码开销。我过去曾使用过与此链接相关的代码。

-很好的狩猎-

C程序比较整数而不使用逻辑运算符?

于 2013-05-13T14:56:27.050 回答