【发布时间】:2012-01-14 10:09:23
【问题描述】:
如何进行反向内存比较?如,我给出了两个序列的结尾,我希望指针在开始时递减,而不是在结束时递增。
【问题讨论】:
-
@VladLazarenko 尽管这是关于比较而不是复制,但我想答案是相同的 - 因此这可以被视为欺骗。
-
我实际上犯了一个小错误,我收回我的投票,对不起大家
如何进行反向内存比较?如,我给出了两个序列的结尾,我希望指针在开始时递减,而不是在结束时递增。
【问题讨论】:
C 标准库中没有内置函数可以做到这一点。下面是一个自己滚动的简单方法:
int memrcmp(const void *s1, const void *s2, size_t n)
{
if(n == 0)
return 0;
// Grab pointers to the end and walk backwards
const unsigned char *p1 = (const unsigned char*)s1 + n - 1;
const unsigned char *p2 = (const unsigned char*)s2 + n - 1;
while(n > 0)
{
// If the current characters differ, return an appropriately signed
// value; otherwise, keep searching backwards
if(*p1 != *p2)
return *p1 - *p2;
p1--;
p2--;
n--;
}
return 0;
}
如果你有高性能的东西,你应该一次比较 4 字节的字而不是单个字节,因为内存延迟将是瓶颈;但是,该解决方案要复杂得多,并不值得。
【讨论】:
很像最初由 Vlad Lazarenko 链接的帖子 (C memcpy in reverse),这里有一个基于此的解决方案,我尚未测试,但应该可以帮助您开始。
int reverse_memcmp(const void *s1, const void *s2, size_t n)
{
unsigned char *a, *b;
a = s1;
b = s2;
size_t i = 0;
// subtracting i from last position and comparing
for (i = 0; i < n; i++) {
if (a[n-1-i] != b[n-1-i]) {
// return differences between different byte, strcmp()-style
return (a[n-1-i] - b[n-1-i]);
}
}
return 0;
}
【讨论】:
void* 指针不能被取消引用。您应该在取消引用之前转换为 unsigned char*。
您需要做的就是指定两端和要比较的大小以及步长。请特别注意,步长可能是获得预期结果的最重要部分。如果您限制大小,它将大大简化实施。对于 char 的大小,您可以执行以下操作:
int compare (void *one, void *two, size_t size)
{
char *one_char = (char *)one;
char *two_char = (char *)two;
size_t i;
for (i = 0; i < size; i++)
{
if (*(one_char - i) != *(two_char - i))
return(NOT_EQUAL);
}
return(EQUAL);
}
【讨论】:
更短的代码(C 代码不需要强制指针类型转换):
int reverse_memcmp(const void *end1, const void *end2, size_t n) {
const unsigned char *a = end1, *b = end2;
for (; n; --n)
if (*--a != *--b) return *a - *b;
return 0;
}
【讨论】: