比较 void * 是否包含 0 个字节?
comparing if void * contains 0 numbytes?
我需要通用方法来检查 void * 是否包含 0 直到 num_bytes。
我想出了以下方法。 *p 每次都不包含相同类型的数据,因此不能 *(type*)p
bool is_pointer_0(void *p, int num) {
void *cmp;
cmp = (void*)malloc(num);
memset(cmp, 0, num);
if (memcmp(p, cmp, num)) {
free(cmp);
return false;
} else {
free(cmp);
return true;
}
}
该函数在每次调用时分配并释放 num 个字节,我认为这不太好。
请建议更快的方法。感谢您的帮助。
更新:
这种方法怎么样?
bool is_pointer_0(void *p, int num) {
void *a = NULL;
memcpy(&a, p, num);
return a == NULL;
}
此代码将 void 指针转换为 char 指针。这允许将指向的内存视为一个字节序列。然后循环遍历指定的长度以查找非零字节。我不知道标准是否保证这会起作用(即将 void* 转换为 char* 将提供指向原始字节的指针),但在现实生活中它起作用
bool is_pointer_0(void *p, int num) {
char *c = (char *)p;
for(int i = 0; i < num; i++)
if(c[i]) return false;
return true;
}
您可以将指针转换为 char*
或 unsigned char*
并检查元素的值。
unsigned char* cp = reinterpret_cast<unsigned char*>(p);
for (int i = 0; i < num; ++i )
{
if ( cp[i] != 0 )
{
return false;
}
}
return true;
我可能会选择这样的东西:
bool is_pointer_0(void* p, int num)
{
return std::search_n((char*)p, (char*)p + num, num, 0) == p;
}
或者这样:
bool is_pointer_0(void* p, int num)
{
return std::all_of((char*)p, (char*)p + num, [](char c){return c == 0;});
}
注意:对于对齐良好的长缓冲区,此方法可能更好。然而 由于简单而快速。
由于内存,如果全为零,必须与自身进行比较,使用 memcmp()
:特定于平台的优化函数。
int memcmp0(const void *buf, size_t n) {
#define TESTVALUE 0
const char *cbuf = (const char *) buf;
while (n > 0) {
// If odd size, last byte not 0?
if (n % 2 && (cbuf[n - 1] != TESTVALUE)) return 0;
// 1st half matches 2nd half?
size_t half = n / 2;
if(memcmp(cbuf, &cbuf[half], half) != 0) return 0;
n = half;
}
return 1;
}
这很容易扩展到 0
以外的其他值,方法是更改 TESTVALUE
。
注意:最多 log2(n)
次迭代。
接受答案后的另一个:
由于内存,如果全为零,必须与自身进行比较,使用memcmp()
:平台特定的优化函数。
检查第一个值,然后使用memcmp()
比较ptr[0],ptr[1]
,然后ptr[1],ptr[2]
,然后ptr[2],ptr[3]
,等等
int memcmpfast(const void *ptr, size_t n, char testvalue) {
const char *cptr = (const char *) ptr;
if (n == 0) return 1;
if (cptr[0] != testvalue) return 0;
return memcmp(cptr, cptr + 1, n - 1) == 0;
}
我需要通用方法来检查 void * 是否包含 0 直到 num_bytes。
我想出了以下方法。 *p 每次都不包含相同类型的数据,因此不能 *(type*)p
bool is_pointer_0(void *p, int num) {
void *cmp;
cmp = (void*)malloc(num);
memset(cmp, 0, num);
if (memcmp(p, cmp, num)) {
free(cmp);
return false;
} else {
free(cmp);
return true;
}
}
该函数在每次调用时分配并释放 num 个字节,我认为这不太好。 请建议更快的方法。感谢您的帮助。
更新:
这种方法怎么样?
bool is_pointer_0(void *p, int num) {
void *a = NULL;
memcpy(&a, p, num);
return a == NULL;
}
此代码将 void 指针转换为 char 指针。这允许将指向的内存视为一个字节序列。然后循环遍历指定的长度以查找非零字节。我不知道标准是否保证这会起作用(即将 void* 转换为 char* 将提供指向原始字节的指针),但在现实生活中它起作用
bool is_pointer_0(void *p, int num) {
char *c = (char *)p;
for(int i = 0; i < num; i++)
if(c[i]) return false;
return true;
}
您可以将指针转换为 char*
或 unsigned char*
并检查元素的值。
unsigned char* cp = reinterpret_cast<unsigned char*>(p);
for (int i = 0; i < num; ++i )
{
if ( cp[i] != 0 )
{
return false;
}
}
return true;
我可能会选择这样的东西:
bool is_pointer_0(void* p, int num)
{
return std::search_n((char*)p, (char*)p + num, num, 0) == p;
}
或者这样:
bool is_pointer_0(void* p, int num)
{
return std::all_of((char*)p, (char*)p + num, [](char c){return c == 0;});
}
注意:对于对齐良好的长缓冲区,此方法可能更好。然而
由于内存,如果全为零,必须与自身进行比较,使用 memcmp()
:特定于平台的优化函数。
int memcmp0(const void *buf, size_t n) {
#define TESTVALUE 0
const char *cbuf = (const char *) buf;
while (n > 0) {
// If odd size, last byte not 0?
if (n % 2 && (cbuf[n - 1] != TESTVALUE)) return 0;
// 1st half matches 2nd half?
size_t half = n / 2;
if(memcmp(cbuf, &cbuf[half], half) != 0) return 0;
n = half;
}
return 1;
}
这很容易扩展到 0
以外的其他值,方法是更改 TESTVALUE
。
注意:最多 log2(n)
次迭代。
接受答案后的另一个:
由于内存,如果全为零,必须与自身进行比较,使用memcmp()
:平台特定的优化函数。
检查第一个值,然后使用memcmp()
比较ptr[0],ptr[1]
,然后ptr[1],ptr[2]
,然后ptr[2],ptr[3]
,等等
int memcmpfast(const void *ptr, size_t n, char testvalue) {
const char *cptr = (const char *) ptr;
if (n == 0) return 1;
if (cptr[0] != testvalue) return 0;
return memcmp(cptr, cptr + 1, n - 1) == 0;
}