Использует ли strlen() условие цикла медленнее, чем просто проверка нулевого символа?

Я читал, что использование 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++)

Ответы

Ответ 1

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).

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

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

int a = strlen(x); 
for (int i = 0; i < a; i++) {...}

Ответ 5

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

Ответ 6

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

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

Это еще O(n).

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

Ответ 7

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

Первая версия эквивалентна следующей:

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

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

Единственный ответ, что и общий, и правильный - это "профиль и узнать".

Ответ 8

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

Я бы предложил:   для (i = 0; я < buf_size & x [i]!= '\ 0'; я ++)

Где:

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