【问题标题】:comparing if void * contains 0 numbytes?比较 void * 是否包含 0 numbytes?
【发布时间】:2015-12-14 17:34:35
【问题描述】:

我需要通用方法来检查 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;
    }

【问题讨论】:

  • 如果我是你,我会在你陷入“使用向量”cmets 之前删除 C++ 标签。
  • 不,标记你实际使用的语言,否则你会得到错误的答案。
  • 您需要定义什么对您来说“更好”:更简单?快点?预包装?
  • 希望采用更快的方法,但循环似乎不可避免。
  • 如果您担心性能问题,您可以对大n 进行矢量化检查。

标签: c void-pointers


【解决方案1】:

此代码将 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;
}

【讨论】:

  • 我们可以避免循环吗?
  • 否;您只能将循环隐藏在某些库函数后面。坦率地说,这个答案可能是我会做的,除非我真的需要让底层操作系统以某种方式一次性为我完成。
  • 刚刚更新了一个不同的方法,你们可以看看
  • 它有什么作用?它是如何工作的?请添加解释以使此答案对未来的访问者更有用。谢谢!
【解决方案2】:

您可以将指针转换为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;

【讨论】:

    【解决方案3】:

    注意:这种方法对于对齐良好的长缓冲区可能更好。然而,this answer 速度很快,因为它很简单。

    由于内存必须与自身比较,如果全为零,请使用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;
    }
    

    这很容易通过更改TESTVALUE 扩展到0 以外的其他值。

    注意:最多log2(n) 次迭代。

    【讨论】:

      【解决方案4】:

      接受答案后的另一个:

      由于内存(如果全为零)必须与自身进行比较,请使用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;
      }
      

      【讨论】:

        【解决方案5】:

        我可能会选择这样的东西:

        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;});
        }
        

        【讨论】:

        • 它有什么作用?它是如何工作的?请添加解释以使此答案对未来的访问者更有用。谢谢!
        猜你喜欢
        • 2011-01-20
        • 2019-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-17
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        相关资源
        最近更新 更多