Как вычислить длину строки в C эффективно?

Как вычислить длину строки в C эффективно (вовремя)?

Прямо сейчас я делаю:

int calculate_length(char *string) {
    int length = 0;
    while (string[length] != '\0') {
        length++;
    }
    return length;
}

Но это очень медленно по сравнению с strlen (), например, есть ли какой-либо другой способ сделать это?

Спасибо.

Править: Я работаю в среде отдельных программ, мне не разрешают использовать внешний lib включая "string.h".

21
задан Carla Álvarez 15 January 2010 в 10:00
поделиться

8 ответов

Самым простым способом является вызов strlen () . Серьезно. Он уже оптимизирован поставщиками компиляторов и/или библиотек, чтобы быть максимально быстрым для вашей архитектуры.

Одной из распространенных оптимизаций является удаление необходимости увеличения счетчика и вычисления длины из указателя:

size_t my_strlen(const char *s)
{
  const char *anchor = s;

  while(*s)
   s++;

  return s - anchor;
}
-121--2109221-

Диапазон является именно таким: что-то определяется его началом и концом, а не его содержимым. «Итерация» в диапазоне не имеет смысла в общем случае. Рассмотрим, например, «итерацию» по диапазону, создаваемому двумя датами. Не могли бы вы повторить по дням? по месяцам? по годам? по неделям? Это не совсем ясно. ИМО, тот факт, что это разрешено для прямых диапазонов, следует рассматривать только как удобный метод.

Если вы хотите повторить назад в таком диапазоне, вы всегда можете использовать downto :

$ r = 10..6
=> 10..6

$ (r.first).downto(r.last).each { |i| puts i }
10
9
8
7
6

Вот еще несколько мыслей от других о том, почему трудно и разрешить итерацию, и последовательно иметь дело с обратными диапазонами.

-121--752756-

Из исходного кода FreeBSD :

size_t
strlen(const char *str)
{
    const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}

По сравнению с вашим кодом, это, вероятно, очень хорошо сопоставляется с командой ассемблера, что может объяснить большую разницу в производительности.

43
ответ дан 29 November 2019 в 06:25
поделиться

C rings Внутренне неэффективность , существуют две причины использования Конвенции ASCIZ:

  • Стандартная библиотека C использует его
  • Компилятор использует его для буквальных строковых констант

Из них академик в этом случае, поскольку вы не используете стандартную библиотеку, вторая легко преодолена путем создания функций или макросов, которые предоставляют преобразования из строк C до более эффективной конвенции, такие как строки Паскаля. Дело в том, что вам не нужно быть рабым к Конвенции C, если вы не используете библиотеку C.

3
ответ дан 29 November 2019 в 06:25
поделиться

Реализуйте и используйте интерфейс INotifyPropertyChanged . Прохладным способом сделать это без последовательности литералов является здесь .

-121--1579638-
  1. PHP - это бэкэнд , PHP - это не та вещь, которая ограничивает использование только «одной» выгрузки за раз
  2. HTML/JavaScript являются фронтальными/средними, которые вызывают ограничения. (Поэтому добавьте HTML к вопросам тэгов)
  3. Если вы используете Flash (AS = ActionScript ), вы можете использовать PHP в качестве внутреннего процессора, который обрабатывает загруженные файлы.
-121--3060208-

На процессорах i386 libc часто используется ультраоптимизированная версия strlen , часто написанная на языке сборки. В статье « Длина последовательности » объясняется, как они работают.

Вот одна оптимизированная версия для OpenBSD . (Они также имеют портативную версию .) Вот версия для GNU libc .

0
ответ дан 29 November 2019 в 06:25
поделиться

Самый простой способ состоит в том, чтобы позвонить Strlen () . Серьезно. Это уже оптимизировано вашим поставщиком компилятора и / или библиотеки, чтобы быть как можно быстрее для вашей архитектуры.

Одна общая оптимизация состоит в том, чтобы удалить необходимость увеличения счетчика, и вычислять длину от указателя:

size_t my_strlen(const char *s)
{
  const char *anchor = s;

  while(*s)
   s++;

  return s - anchor;
}
3
ответ дан 29 November 2019 в 06:25
поделиться

strlen () . Шансы того, что если бы кто-то нашел лучший, более быстрый общий метод, Стрлен был бы заменен этим.

-121--2109224-

SQL для Smarties Джо Селко. Мне нравится, путь он охватывает методы представления наборов данных, которые, по вашему мнению, не сразу впишутся в реляционную модель.

alt text
(источник: amazon.com )

-121--3894514-

Посмотрите на библиотеку GNU C strlen () источник .

Он использует ряд неочевидных трюков, чтобы набрать скорость, не опускаясь на сборку, в том числе:

  • добраться до символа, который правильно выровнен
  • считывая эти выровненные части строки в int (или какой-то больший тип данных), чтобы прочитать несколько символов за раз
  • , используя битовые трюки, чтобы проверить, является ли один из символов, встроенных в этот блок chars равен нулю

и т.д.

6
ответ дан 29 November 2019 в 06:25
поделиться

Взгляните на исходный код strlen в стандартной libc. Функции в стандартных библиотеках, как правило, сильно оптимизированы. Посмотрите здесь (закодировано в сборке) - это из GNU libc.

size_t
DEFUN(strlen, (str), CONST char *str)
{
  int cnt;

  asm("cld\n"                   /* Search forward.  */
      /* Some old versions of gas need `repne' instead of `repnz'.  */
      "repnz\n"                 /* Look for a zero byte.  */
      "scasb" /* %0, %1, %3 */ :
      "=c" (cnt) : "D" (str), "0" (-1), "a" (0));

  return -2 - cnt;
}
9
ответ дан 29 November 2019 в 06:25
поделиться

Еще один способ ускорить счетчик Char - использовать векторизацию!

Вот пример того, как это сделать по отношению к строкам, закодированным UTF8:

Даже быстрее подсчет символов UTF-8,

http://www.daemonology.net/blog/2008-06-05 -Faster-utf8-strlen.html

2
ответ дан 29 November 2019 в 06:25
поделиться

strlen(). Скорее всего, если бы кто-нибудь нашел лучший, более быстрый универсальный метод, то strlen был бы заменен на него.

9
ответ дан 29 November 2019 в 06:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: