Ответ 1
Возможность встроить вызов функции - это как оптимизация для компилятора, так и обычное поведение. То есть многие компиляторы могут это сделать, но они не требуются.
Иногда необходимо сравнить длину строки с константой.
Например:
if ( line.length() > 2 )
{
// Do something...
}
Но я стараюсь избегать использования "магических" констант в коде.
Обычно я использую такой код:
if ( line.length() > strlen("[]") )
{
// Do something...
}
Это более читаемо, но не эффективно из-за вызова функции.
Я написал функции шаблона следующим образом:
template<size_t N>
size_t _lenof(const char (&)[N])
{
return N - 1;
}
template<size_t N>
size_t _lenof(const wchar_t (&)[N])
{
return N - 1;
}
// Using:
if ( line.length() > _lenof("[]") )
{
// Do something...
}
В сборке релизов (VisualStudio 2008) он создает довольно хороший код:
cmp dword ptr [esp+27Ch],2
jbe 011D7FA5
И хорошо, что компилятор не включает строку "[]" в двоичном выходе.
Является ли это конкретной оптимизацией для компилятора или это обычное поведение?
Возможность встроить вызов функции - это как оптимизация для компилятора, так и обычное поведение. То есть многие компиляторы могут это сделать, но они не требуются.
Почему бы не
sizeof "[]" - 1;
(минус один для конечного нуля. do sizeof "[]" - sizeof '\ 0', но sizeof '\ 0' часто является sizeof (int) в C, а "- 1" является отлично читаемый.)
Я думаю, что большинство компиляторов оптимизируют его, когда оптимизация включена. Если они отключены, это может замедлить вашу программу намного больше, чем необходимо.
Я бы предпочел использовать ваши функции шаблонов, так как они гарантированно не вызывают strlen
во время выполнения.
Конечно, вместо того, чтобы писать отдельные функции для char
и wchar_t
, вы можете добавить еще один аргумент шаблона и получить функцию, которая работает для любого типа:
template <typename Char_t, int len>
int static_strlen(const Char_t (&)[N] array){
return len / sizeof(Char_t) - 1;
}
(Как уже упоминалось в комментариях, это даст смешные результаты, если передать массив из int, но вы, вероятно, это сделаете? Это означало для строк, в конце концов)
Наконец, имя _strlen
плохое. Все имена в области пространства имен, начинающиеся с символа подчеркивания, зарезервированы для реализации. Вы рискуете некоторыми неприятными конфликтами именования.
Кстати, почему "[]" меньше магической константы, чем 2?
В обоих случаях это литерал, который нужно изменить, если формат строки, который он сравнивает с изменениями.
#define TWO 2
#define STRING_LENGTH 2
/* ... etc ... */
Серьезно, зачем проходить все эти хлопоты, чтобы не набирать 2? Я честно думаю, что вы делаете свой код менее удобочитаемым, а другие программисты будут смотреть на вас, как будто вы фыркаете использованный кофе из фильтра.