Использование strlen () в условии цикла медленнее, чем просто проверка на нулевой символ? - PullRequest
14 голосов
/ 02 августа 2010

Я читал, что использование strlen дороже, чем такое тестирование, как это:

У нас есть строка x 100 символов.

Я думаю, что

for (int i = 0; i < strlen(x); i++)

дороже, чем этот код:

for (int i = 0; x[i] != '\0'; i++)

Это правда? Может быть, второй код не будет работать в некоторых ситуациях, так что лучше использовать первый?

Будет ли лучше с нижеследующим?

for (char *tempptr = x; *tempptr != '\0'; tempptr++)

Ответы [ 8 ]

26 голосов
/ 02 августа 2010
for (int i=0;i<strlen(x);i++)

Этот код вызывает strlen(x) каждую итерацию. Поэтому, если x - это длина 100, strlen(x) будет вызываться 100 раз. Это очень дорого Кроме того, strlen(x) также выполняет итерации по x каждый раз так же, как ваш цикл for. Это усложняет O (n ^ 2).

for (int i=0;x[i]!='\0';i++)

Этот код не вызывает функций, поэтому будет намного быстрее, чем в предыдущем примере. Поскольку он повторяет цикл только один раз, это сложность O (n).

11 голосов
/ 02 августа 2010

Первый код проверяет длину x на каждой итерации i, и для нахождения последнего 0 требуется O (n), поэтому требуется O (n ^ 2), во втором случае O (n)

4 голосов
/ 02 августа 2010

Да, ваша секунда может не работать в 100% случаев, но это будет совсем немного. Это потому, что при использовании strlen () вы должны вызывать метод каждый раз. Лучше было бы так

int strLength = strlen(x);
for (int i = 0; i < strLength; i++)

Надеюсь, это поможет.

2 голосов
/ 02 августа 2010

Полагаю, компилятор мог бы оптимизировать (см. Комментарий Грегори Пакоша) ваш первый цикл for, чтобы вы выглядели так:

int len = strlen(x);
for (int i = 0; i < len; i++)

Что все еще равно O(n).

В любом случаеЯ думаю, ваш второй цикл for будет быстрее.

2 голосов
/ 02 августа 2010

Если нет, то нет оптимизации компиляции. Да, потому что strlen будет повторять каждый байт строки каждый раз, а вторая реализация сделает это только один раз.

2 голосов
/ 02 августа 2010

Я могу предположить, что в первом варианте вы найдете strlen каждую итерацию, а во втором варианте вы этого не делаете.
Попробуйте это проверить:

int a = strlen(x); 
for (int i = 0; i < a; i++) {...}
0 голосов
/ 02 августа 2010

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

Я бы предложил:for (i = 0; i

Где:

  • buf_size - это предопределенный размер буфера,Если x является массивом, это будет sizeof(x);если x - указатель, у вас должен быть доступный размер буфера.
  • Я удалил объявление i из цикла, потому что это только допустимый c99.Если вы компилируете только под c99, смело возвращайте его обратно.
0 голосов
/ 02 августа 2010

Конечно первый займет больше времени, чем второй. На самом деле они вообще не делают одно и то же - первый вычисляет длину строки каждый раз; второй (эффективно) делает это только один раз.

Первая версия эквивалентна этому:

for (int i=0; x[i] != 0; i++)
  for (int j=0; j<i; j++)
    ;

Может быть, вы хотели сказать "более эффективно вызывать библиотеку strlen (), чем реализовывать мою собственную?" Ответ на это, конечно, «это зависит». Ваш компилятор может иметь встроенные версии strlen (), которые оптимизированы сверх того, что вы ожидаете от исходного кода, вы можете быть на платформе, на которой вызовы функций дороги (в настоящее время редки) и т. Д.

Единственный общий и правильный ответ - «узнай и узнай».

...