为什么负数大于正数?
Why are negative numbers greater than positive numbers?
我使我的冒泡排序程序通用。我继续测试它,它运行良好,直到我在数组中放置一个负数,令我惊讶的是它被推到最后,使其大于正数。
显然memcmp
是这个道理,那么为什么memcmp()
认为负数大于正数呢?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bubblesortA(void *_Buf, size_t bufSize, size_t bytes);
int main(void)
{
size_t n, bufsize = 5;
int buf[5] = { 5, 1, 2, -1, 10 };
bubblesortA(buf, 5, sizeof(int));
for (n = 0; n < bufsize; n++)
{
printf("%d ", buf[n]);
}
putchar('\n');
char str[] = "bzqacd";
size_t len = strlen(str);
bubblesortA(str, len, sizeof(char));
for (n = 0; n < len; n++)
{
printf("%c ", str[n]);
}
putchar('\n');
return 0;
}
void bubblesortA(void *buf, size_t bufSize, size_t bytes)
{
size_t x, y;
char *ptr = (char*)buf;
void *tmp = malloc(bytes);
for (x = 0; x < bufSize; x++)
{
ptr = (char *)buf;
for (y = 0; y < (bufSize - x - 1); y++)
{
if (memcmp(ptr, ptr + bytes, bytes) > 0)
{
memcpy(tmp, ptr, bytes);
memcpy(ptr, ptr + bytes, bytes);
memcpy(ptr + bytes, tmp, bytes);
}
ptr += bytes;
}
}
free(tmp);
}
编辑:
那么,如何修改程序使其正确比较?
memcmp
比较字节,不知道字节代表的是int
s,double
s,字符串,...
因此,将字节视为无符号数再好不过了。因为负整数通常使用二进制补码表示,所以设置了负整数的最高位,使其大于任何正符号整数。
负数的符号位(最高有效位)设置为 1。函数 memcmp
将字节作为无符号值进行比较。因此它将符号位视为值位。结果有时负数大于正数。
在对数和负数进行计数的表示法中,第一位用作符号位,表示一个数是负数还是正数。
如果我们看一下 2 个数字的二进制表示,就会一目了然。值得注意的是 memcmp
只是比较 2 个数字,就好像它们都是指定长度的无符号数字一样。
-27 二进制表示法(8 位表示法,二进制补码):1110 0101
+56 二进制表示法:0011 1000
如果将两者作为正数进行比较,您会注意到 -27 表示实际上更大。
正在回答 OP 的附加编辑
How can i modify the program to make it compare correctly?
要将两种类型作为匿名位模式进行比较,memcmp()
可以正常工作。要比较某种类型的两个值,代码需要该类型的比较函数。以下 qsort()
风格:
void bubblesortA2(void *_Buf,size_t bufSize,size_t bytes,
int (*compar)(const void *, const void *)))
{
....
// if(memcmp(ptr,ptr+bytes,bytes) > 0)
if((*compar)(ptr,ptr+bytes) > 0)
....
要比较int
,传入一个比较int
函数。请注意,a
、b
是对象的地址。
int compar_int(const void *a, const void *b) {
const int *ai = (const int *)a;
const int *bi = (const int *)b;
return (*ai > *bi) - (*ai < *bi);
}
要比较 char
,传入比较 char
函数
int compar_int(const void *a, const void *b) {
const char *ac = (const char *)a;
const char *bc = (const char *)b;
return (*ac > *bc) - (*ac < *bc);
}
我使我的冒泡排序程序通用。我继续测试它,它运行良好,直到我在数组中放置一个负数,令我惊讶的是它被推到最后,使其大于正数。
显然memcmp
是这个道理,那么为什么memcmp()
认为负数大于正数呢?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bubblesortA(void *_Buf, size_t bufSize, size_t bytes);
int main(void)
{
size_t n, bufsize = 5;
int buf[5] = { 5, 1, 2, -1, 10 };
bubblesortA(buf, 5, sizeof(int));
for (n = 0; n < bufsize; n++)
{
printf("%d ", buf[n]);
}
putchar('\n');
char str[] = "bzqacd";
size_t len = strlen(str);
bubblesortA(str, len, sizeof(char));
for (n = 0; n < len; n++)
{
printf("%c ", str[n]);
}
putchar('\n');
return 0;
}
void bubblesortA(void *buf, size_t bufSize, size_t bytes)
{
size_t x, y;
char *ptr = (char*)buf;
void *tmp = malloc(bytes);
for (x = 0; x < bufSize; x++)
{
ptr = (char *)buf;
for (y = 0; y < (bufSize - x - 1); y++)
{
if (memcmp(ptr, ptr + bytes, bytes) > 0)
{
memcpy(tmp, ptr, bytes);
memcpy(ptr, ptr + bytes, bytes);
memcpy(ptr + bytes, tmp, bytes);
}
ptr += bytes;
}
}
free(tmp);
}
编辑:
那么,如何修改程序使其正确比较?
memcmp
比较字节,不知道字节代表的是int
s,double
s,字符串,...
因此,将字节视为无符号数再好不过了。因为负整数通常使用二进制补码表示,所以设置了负整数的最高位,使其大于任何正符号整数。
负数的符号位(最高有效位)设置为 1。函数 memcmp
将字节作为无符号值进行比较。因此它将符号位视为值位。结果有时负数大于正数。
在对数和负数进行计数的表示法中,第一位用作符号位,表示一个数是负数还是正数。
如果我们看一下 2 个数字的二进制表示,就会一目了然。值得注意的是 memcmp
只是比较 2 个数字,就好像它们都是指定长度的无符号数字一样。
-27 二进制表示法(8 位表示法,二进制补码):1110 0101
+56 二进制表示法:0011 1000
如果将两者作为正数进行比较,您会注意到 -27 表示实际上更大。
正在回答 OP 的附加编辑
How can i modify the program to make it compare correctly?
要将两种类型作为匿名位模式进行比较,memcmp()
可以正常工作。要比较某种类型的两个值,代码需要该类型的比较函数。以下 qsort()
风格:
void bubblesortA2(void *_Buf,size_t bufSize,size_t bytes,
int (*compar)(const void *, const void *)))
{
....
// if(memcmp(ptr,ptr+bytes,bytes) > 0)
if((*compar)(ptr,ptr+bytes) > 0)
....
要比较int
,传入一个比较int
函数。请注意,a
、b
是对象的地址。
int compar_int(const void *a, const void *b) {
const int *ai = (const int *)a;
const int *bi = (const int *)b;
return (*ai > *bi) - (*ai < *bi);
}
要比较 char
,传入比较 char
函数
int compar_int(const void *a, const void *b) {
const char *ac = (const char *)a;
const char *bc = (const char *)b;
return (*ac > *bc) - (*ac < *bc);
}