比较两个整数的通用函数?

时间:2013-05-13 05:39:08

标签: c

是否有一个相当标准的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 个答案:

答案 0 :(得分: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 ... */
        }
}

答案 1 :(得分: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;
}

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

答案 2 :(得分:0)

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

- 好狩猎 -

C program to compare integers without using logical operators?

答案 3 :(得分:0)

如果呼叫站点的大小可用,我宁愿将其用作查找表中的索引,只需立即调用正确的函数。