vindyz
vindyz

Reputation: 1101

comparing if void * contains 0 numbytes?

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

Answers (5)

chux
chux

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

chux
chux

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

pm100
pm100

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

Galik
Galik

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

R Sahu
R Sahu

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

Related Questions