Как рассчитать последовательные нулевые (\ 0) байты в C? - PullRequest
0 голосов
/ 02 апреля 2012

Есть ли быстрый способ подсчитать количество последовательных нулевых байтов, начиная с определенного (char *) указателя в C? В настоящее время я использую жесткий цикл, который работает хорошо и достаточно быстро, но строковые функции libc / gcc имеют тенденцию быть еще быстрее.

Я ищу что-то похожее на strspn, но buf strspn (конечно) останавливается на первом нулевом байте и поэтому бесполезен для этой задачи. Я думаю, вы могли бы также сказать, что я ищу инверсию strlen, которая возвращает число байтов, которые не null.

Ответы [ 4 ]

3 голосов
/ 02 апреля 2012

Я не знаю, существует ли такой метод, но если вам придется написать его самостоятельно, вы можете рассмотреть возможность проверки наборов по 4 или 8 байтов вместе, используя (int*) или (long*).

2 голосов
/ 02 апреля 2012

Нет более быстрого способа сделать это в переносимом, стандартном C.

Встроенные компиляторы C и стандартная библиотека могут работать быстрее, потому что их не нужно писать в переносимом, стандартном C- они могут свободно использовать знания, специфичные для реализации.

Вы, конечно, могли бы пойти по этому пути самостоятельно - но если то, что у вас есть, уже достаточно быстро, то действительно ли оно стоит затрат на переносимость и ремонтопригодность?

2 голосов
/ 02 апреля 2012

Если ваш указатель выровнен по словам, вы можете проверить его на нулевое значение слова за раз.

int zeros(char *p)
{
  int n = 0;
  if ((int)p & 1) {
    if (*p)
      return 0;
    p++;
    n++;
  }
  if ((int)p & 2) {
    if (*(short *)p)
      goto label1;
    p += 2;
    n += 2;
  }
  if ((int)p & 4) {
    if (*(long *)p)
      goto label2;
    p += 4;
    n += 4;
  }
  while (!*(long long *)p) {
    p += 8;
    n += 8;
  }
  if (!*(long *)p) {
    p += 4;
    n += 4;
  }
label2:
  if (!*(short *)p) {
    p += 2;
    n += 2;
  }
label1:
  if (!*p)
    n++;
  return n;
}
2 голосов
/ 02 апреля 2012

Как насчет этого?

char* start = ...
char* act = start;
while (*act++ == 0);
ptrdiff_t nulls = (act - start) - 1; 

Однако что-то должно гарантировать остановку , а до того, как он достигнет недоступной памяти

...