如何检查内存块中的所有字节是否为零

Ans*_*mpe 26 c++

我有一块内存块,其中包含固定大小的元素,比如说100个字节,一个接一个地放入,所有内容都有相同的固定长度,所以内存看起来像这样

<element1(100 bytes)><element2(100 bytes)><element3(100 bytes)>...
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我需要确定某个元素的所有字节是否都设置为0字节,因为它具有特殊含义(我没有说这是一个好主意,但这就是我所处的情况).

问题是,我该如何有效地做到这一点.进一步:有一个简单的功能来做到这一点.为了将字节设置为零,我可以使用memset或bzero,但我不知道检查零的任何函数.

目前我正在使用循环进行检查

char *elementStart = memoryBlock + elementNr*fixedElementSize;
bool special = true;
for ( size_t curByteNr=0; curByteNr<fixedElementSize; ++curByteNr )
{
  special &= (*(elementStart+curByteNr)) == 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,我可以使用更大的偏移量循环,并使用mword或其他更适合的更大类型一次检查几个字节.我想这样会很有效率,但我想知道是否有一种功能可以减轻我的负担.

建议功能:

  • !memcmp(compareBlock,myBlock,fixedElementSize)

小智 26

你可能实际上可以使用memcmp而不必分配零值数组,如下所示:

static int memvcmp(void *memory, unsigned char val, unsigned int size)
{
    unsigned char *mm = (unsigned char*)memory;
    return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0;
}
Run Code Online (Sandbox Code Playgroud)

memcmp的标准没有说明重叠内存区域的任何内容.

  • 太好了 实际上,就像@kwesolowski所暗示的那样,单字节可能会引起问题。可以首先检查7个字节,然后调用memcmp(mm,mm + 8,size-8)来解决。也许不是-我可以相信memcmp的某些或大多数实现是从检查重叠开始的,如果是的话,请使用缓慢的简单方法。 (3认同)
  • 函数调用开销和调用多个具有单个字节偏移量的指针的“ memcmp”会消除使用“ memcmp”带来的任何好处,简单的for循环将是更好的遍历时间并且更具可读性。 (2认同)

wal*_*lyk 18

显而易见的便携式高效方法是:

char testblock [fixedElementSize];
memset (testblock, 0, sizeof testblock);

if (!memcmp (testblock, memoryBlock + elementNr*fixedElementSize, fixedElementSize)
   // block is all zero
else  // a byte is non-zero
Run Code Online (Sandbox Code Playgroud)

memcmp()大多数实现中的库函数将使用它可以用于大多数比较的最大,最有效的单元大小.

为了提高效率,请不要testblock在运行时设置:

static const char testblock [100];
Run Code Online (Sandbox Code Playgroud)

根据定义,除非有初始化程序,否则静态变量会自动初始化为零.

  • 正如wallyk所提到的,创建比较块的开销是由memcmp非常有效的事实所抵消的,因为体面的实现比较了机器的字节顺序中的内存并且比较是块对齐的(除了"非常"之外不会被注意到大量"记忆".std :: upper_bound没有这个属性,但是"更多c ++",因为它是一个合适的模板向量迭代器. (2认同)
  • 正如Benjamin Lindley所提到的,std :: upper甚至没有在非排序范围内搜索的属性.所以memcmp获胜. (2认同)
  • memcmp通过`unsigned char`比较`unsigned char`,因为它对返回值的要求是__ memcmp()函数返回一个大于,等于或小于零的整数,因为s1指向的对象大于,等于或小于s2_指向的对象.一个更好的解决方案是编写一个优化的代码,以使用可用的最大字大小,填补极限空白 (2认同)

und*_*e_d 7

我不敢相信还没有人发布这个......一个实际上看起来像 C++ 并且不是用于打破别名规则的 UB 的解决方案:

#include <algorithm> // std::all_of
#include <cstddef>   // std::size_t

// You might only need this
bool
memory_is_all_zeroes(unsigned char const* const begin,
                     std::size_t          const bytes)
{
    return std::all_of( begin, begin + bytes,
                        [](unsigned char const byte) { return byte == 0; } );
}

// but here's this as a bonus
template<typename T_Element, std::size_t T_count>
bool
array_is_all_zeroes( T_Element const (& array)[T_count] )
{
    auto const begin = reinterpret_cast<unsigned char const*>(array);
    auto const bytes = T_count * sizeof(T_Element);

    return memory_is_all_zeroes(begin, bytes);
}

int
main()
{
    int const blah[1000]{0};

    return !array_is_all_zeroes(blah);
}
Run Code Online (Sandbox Code Playgroud)

这可能无法满足某些人对效率的假设(这只是假设,直到被分析),但我认为有效和惯用的代码非常有利于它。