Вопрос: должен ли компилятор пытаться преобразовать
for(i = 0; i < strlen(str); i++)
во что-нибудь вида
for(i = 0; str[i]; i++)
?
Я считаю, что не должен - даже если видно, что операторы внутри цикла не изменяют длину строки (и строка не volatile).
Если пользователю охота превратить линейную сложность в квадратичную - его право. А дело компилятора - выдать предупреждение. "Вы вот здесь поставили strlen, а он не нужен. Потрудитесь убрать, а то вдруг будете компилировать другим компилятором, а он такого не скажет."
Кстати, когда я учился в универе, были в нашей группе умники, которые умудрялись такое писать... Например, есть массив чисел, надо найти минимальное и максимальное число. Так это горе-кодеры искали минимум и максимум в отдельных циклах.
Сейчас попробовал "скомпилировать" в ассемблер вот такую программу:
#include <stdio.h>
#include <string.h>
int main ()
{
char *s = "Test";
int i;
for(i = 0; i < strlen(s); i++)
{
printf("%c\n", s[i]);
}
}
И как вариант, её же, но с s[i] вместо strlen.
Выяснилось, что по умолчанию GCC не "оптимизирует" strlen в предложенном смысле, а честно заменяет на цикл. Причём всегда подставляет функцию вместо её вызова, даже при -O0.
А вот с -O3 - таки да, оптимизирует...
Я сейчас открою страшную тайну: на ЛОРовском форуме помимо раздела "Talks" существует раздел "Development", предназначенный (кто бы мог подумать??) для вопросов, касающихся программирования.
компилятор не только может, но и должен делать оптимизацию простирающуюся за пределами одной функции. Разумеется если он знает что делает данная функция.
Он знает что делает данная функция в 2 случаях -- он видит ее код (например она инлайн), либо она есть в стандарте и ты инклюдишь стандартный хедер который ее объявляет.
Таким образом он может и должен делать оптимизацию strlen
Хм. Пользователь в цикле может удалить строку и выделить под нее новую (большую или меньшую) внутри цикла. Теоретически это возможно, тем более это может происходить не в тексте программы, а при передачи указателя на строку в какую-нибудь неизвестную функцию из разделяемой библиотеки... Так что strlen необходим.
А вообще, for(i = 0; i < m; i++) это тоже глупо. Надо писать for(p = str; p < str_end; p++) , т.к. { p++ } - быстрее чем { i++; p[i] }
There's no way to use volatile for these things, since it can hit
*anything*. When the compiler generates buggy code, it's buggy code. We
can't add volatiles to every single data structure. We'd be better off
having a million monkeys on crack try to hand-assemble the thing, than
having a totally buggy compiler do it for us.
Ну так чо, есть же специальное слово, которым обозначаются переменные, значение которых может быть изменено извне потока команд. Если слово не сказано - значит автор программы сам себе ЗБ.