Reputation: 1101
I need generic way to check if void * contains 0 till num_bytes.
I came up with following approach. *p does not contain same type of data everytime hence cant do *(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;
}
}
The function allocates & frees up num bytes on every call, not pretty I think. Please suggest faster approaches. Appreciate the help.
Update :
How about this approach ?
bool is_pointer_0(void *p, int num) {
void *a = NULL;
memcpy(&a, p, num);
return a == NULL;
}
Upvotes: 5
Views: 159
Reputation: 153517
Note: this approach may be better for long buffers well aligned. Yet this answer is fast due to simplicity.
Since the memory, if all zeros, must compare to itself, use memcmp()
: a platform specific optimized function.
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;
}
This is easy to extend to other values other than 0
by changing TESTVALUE
.
Note: at most log2(n)
iterations.
Upvotes: 1
Reputation: 153517
Another after accept answer:
Since the memory, if all zeros, must compare to itself, use memcmp()
: a platform specific optimized function.
Check the first value and then use memcmp()
to compare ptr[0],ptr[1]
, then ptr[1],ptr[2]
, then ptr[2],ptr[3]
, etc.
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;
}
Upvotes: 0
Reputation: 50190
This code casts the void pointer to a char pointer. This allows the memory pointed at to be treated as a sequence of bytes. Then cycles through the specified length looking for non zero bytes. I do not know if the standards guarantee that this would work (ie casting a void* to a char* will provide a pointer to the raw bytes), but in real life it works
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;
}
Upvotes: 8
Reputation: 48625
I'd probably go with something like this:
bool is_pointer_0(void* p, int num)
{
return std::search_n((char*)p, (char*)p + num, num, 0) == p;
}
Or this:
bool is_pointer_0(void* p, int num)
{
return std::all_of((char*)p, (char*)p + num, [](char c){return c == 0;});
}
Upvotes: -1
Reputation: 206617
You can cast the pointer to a char*
or unsigned char*
and check the values of the elements.
unsigned char* cp = reinterpret_cast<unsigned char*>(p);
for (int i = 0; i < num; ++i )
{
if ( cp[i] != 0 )
{
return false;
}
}
return true;
Upvotes: 4