Сравнивать, если void * содержит 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;
}
5 ответов
Этот код преобразует пустой указатель в указатель на символ. Это позволяет использовать указанную память как последовательность байтов. Затем перебирает указанную длину в поисках ненулевых байтов. Я не знаю, гарантируют ли стандарты, что это будет работать (т.е. приведение 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;
Примечание: этот подход может быть лучше для хорошо выровненных длинных буферов. Тем не менее, этот ответ быстрый из-за простоты.
Поскольку память, если все нули, должны сравнивать с собой, используйте 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;
}
Я бы, наверное, пошел с чем-то вроде этого:
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;});
}