用 memcmp() 比较整数

Comparing integers with memcmp()

我正在制作一个函数来获取 NMEMB 成员数组的最大值,每个成员的大小都是 SIZ, 将每个成员与 memcmp() 进行比较。问题是当比较有符号整数时,结果不正确但同时是正确的。这是一个例子:

void *
getmax(const void *data, size_t nmemb, size_t siz){

    const uint8_t *bytes = (const uint8_t *)data;
    void *max = malloc(siz);

    if (!max){
        errno = ENOMEM;
        return NULL;
    }
    
    memcpy(max, bytes, siz);
    while (nmemb > 0){

        hexdump(bytes, siz);

        if (memcmp(max, bytes, siz) < 0)
            memcpy(max, bytes, siz);

        bytes += siz;
        --nmemb;
    }

    return max;
}

int
main(int argc, char **argv){
    int v[] = {5, 1, 3, 1, 34, 198, -12, -11, -0x111118};
    size_t nmemb = sizeof(v)/sizeof(v[0]);
    int *maximum = getmax(v, nmemb, sizeof(v[0]));
    printf("%d\n", *maximum);
    return 0;
}

编译执行时输出如下:

05 00 00 00 // hexdump() output
01 00 00 00
03 00 00 00
01 00 00 00
22 00 00 00
c6 00 00 00
f4 ff ff ff
f5 ff ff ff
e8 ee ee ff
-11  // "maximum" value

这是正确的,因为 memcmp() 比较字节串并且不关心类型或符号所以 -11 = 0xfffffff5 是数组 v[] 中的最大字节串但是在同样的时间是不正确的,因为 -11 不是数组中的最大整数。

有什么方法可以使用此函数获取数组的最大整数吗?

沿着 qsort 路线走下去,需要一个自定义比较器。请注意,您绝对不需要在这么简单的函数中进行动态内存分配:

#include <stdio.h>

void const *getmax(void const *data, size_t const count, size_t const elm_sz,
                   int (*cmp)(void const *, void const *)) {
  char const *begin = data;
  char const *end = begin + count * elm_sz;
  char const *max = begin;
  while (begin != end) {
    if (cmp(max, begin) < 0) max = begin;
    begin += elm_sz;
  }

  return max;
}

int int_cmp(void const *e1, void const *e2) {
  int const i1 = *(int const *)e1;
  int const i2 = *(int const *)e2;

  if (i1 > i2) return 1;
  if (i1 < i2) return -1;
  return 0;
}

int main() {
  int v[] = {5, 1, 3, 1, 34, 198, -12, -11, -0x111118};
  int const *maximum = getmax(v, sizeof(v) / sizeof(*v), sizeof(*v), int_cmp);
  printf("%d\n", *maximum);
}

memcmp比较位置,不在乎符号。所以对于它 -11 表示 0xFFFFFFF5 并且 -12 表示 0xFFFFFFF4 并且数组中最大的数字 198 表示 0x000000C6,所以在所有这些中, -11 是最大的无符号数,给你返回。您不应该使用 memcmp 来比较带符号的数字。

memcmp 进行的所有内存比较都是无符号的,并且基于 char 大小的数组元素。当你用 signed int 单元格数组提供它时,不同大小,你的结果只能用于测试二进制表示的相等性,这意味着 0 或不同于 0 的结果意味着相等或不相等,但符号不同的零结果意味着比较整数数组的各个字节,这些字节被分解为字节(在机器字节序体系结构中),使一些字节被签名并作为无符号和其他人被签名并与未签名进行比较。此外,整数中不同字节的重要性可能会影响排序顺序,因为字节是从低地址到高地址进行比较的,只有在整数存储为 unsigned 并且(非常重要)以大端顺序存储在内存中。如果您可能正在使用英特尔架构,那么这恰恰相反。