C指针数组的int比较器



我正在学习LCTHW教程,我有一项任务要做。这是数据结构:

typedef struct DArray {
int end;
int max; 
size_t element_size;
size_t expand_rate;
void **contents; 
} DArray;

我已经声明了一个typedef:

typedef int (*DArray_compare) (const void *a, const void *b);

当我创建一个排序函数时,我会向它传递一个DArray_compare,问题是我不知道如何做这个比较器的例子。

我试着做这样的事情:

int compare(const void *a, const void *b)
{
int i = (int)*a;
int k = (int)*b;
printf("%d %dn", i, k);
return i - k;
}

但我得到了一个错误:

error: operand of type 'void' where arithmetic or pointer type is required int i = (int)*a;

问题是:在不改变比较器的结构和typedef的情况下,我想创建一个比较int的比较器,我该怎么做?

int i = *(int*)a;
// This one has more parens to make it really obvious what your intent is.
int k = *((int*)b);

第二行(k=)最容易解释所有括号的cos。您可以将其重写如下:

// Cast b from a pointer to a void into a pointer to an int.
int *X = (int*)b; 
// k = "what X is pointing to" or "the contents of X"
int k = *X;

编辑:我认为ralu的评论是建议您将所有void*更改为int*,如果您有这种能力,这是一个更安全的解决方案。

typedef int (*DArray_compare) (const int *a, const int *b);
int compare(const int *a, const int *b)
{
int i = *a;
int k = *b;
...

DArray结构数组的标准C库中与bsearch()qsort()一起使用的比较函数可能如下所示:

int compare(const void *a, const void *b)
{
const DArray *d1 = a;
const DArray *d2 = b;
if (d1->end < d2->end)
return -1;
else if (d1->end > d2->end)
return +1;
else if (d1->max < d2->max)
return -1;
else if (d2->max > d2->max)
return +1;
else
return 0;
}

显然,如果您需要比较其他字段,您可以很容易地将这些比较添加到上面的框架中。函数的一般结构是我推荐的编写此类比较器的方法。如果愿意,可以向赋值行添加显式强制转换;C++需要它们,但C不需要。

请注意,您的typedef与比较器本身的相关性最小(尽管作为函数指针的比较器应该与typedef匹配)。这是比较器应该具有的类型,但在编写函数时不能使用typedef名称。您可以在排序函数的实现及其声明中使用typedef


我在几个地方观察到,作为比较器的结果返回两个有符号int值的差会导致未定义的行为。

AR89在对一个现已删除的答案的评论中问道:

如果不进行减法运算,if语句会更安全吗?

是。考虑一下,如果您有16位的int值,并比较-30000和+30000会发生什么;有符号溢出,您可能会从比较器中得到一个正值,即使第一个值小于第二个值。类似的情况可能发生在32位或64位整数中。它们相对来说不太可能;如果你知道你的值在范围内,你就可以了。但对于通用代码,你应该进行分段比较:

if (i < k)
return -1;
else if (i > k)
return +1;
else
return 0;

因为不管CCD_ 11和CCD_。还要注意,if比较也适用于unsigned int类型,而减法则不起作用(结果总是零或正)。

相关内容

  • 没有找到相关文章

最新更新