Strlen c что означает
Синтаксис
Параметры
str
Строка, завершающаяся символом NULL.
locale
Используемый языковой стандарт.
Возвращаемое значение
Комментарии
strlen интерпретирует строку как строку однобайтовых символов, поэтому возвращаемое значение всегда равно числу байт, даже если строка содержит многобайтовые символы. wcslen — это версия strlen с расширенными символами; аргумент wcslen — строка расширенных символов, а число символов выражается в расширенных (двухбайтовых) символах. Поведение wcslen и strlen идентично в противном случае.
Примечание о безопасности. Эти функции предполагают потенциальную угрозу, связанную с проблемой переполнения буфера. Проблемы переполнения буфера — это распространенный метод атак на системы, который приводит к несанкционированному повышению уровня прав. Дополнительные сведения см. в разделе Как избежать переполнения буфера.
По умолчанию глобальное состояние этой функции ограничивается приложением. Чтобы изменить это, см. раздел глобальное состояние в CRT.
Универсальное текстовое сопоставление функций
TCHAR.H ассемблер | _UNICODE & _MBCS не определено | _MBCS определяется | _UNICODE определяется |
---|---|---|---|
_tcslen | strlen | strlen | wcslen |
_tcsclen | strlen | _mbslen | wcslen |
_tcsclen_l | strlen | _mbslen_l | wcslen |
Требования
Дополнительные сведения о совместимости см. в статье Compatibility.
Как не сделать самый быстрый strlen и найти недоработку в Visual Studio 2019 Community
Нуль-терминированная строка — способ представления строк в языках программирования, при котором вместо введения специального строкового типа используется массив символов, а концом строки считается первый встретившийся специальный нуль-символ (NUL из кода ASCII, со значением 0).
Для определения длины таких срок применяется стандартная функция
Алгоритм работы которой можно описать на языке Си как:
Посмотрим, во что его превращает компилятор MS Visual Studio 2019 community (Release, x86):
То есть происходит загрузка из памяти одного байта и сравнение его с нулем. Такой же код подставляется в места вызовов strlen если собирать проект в Release, алгоритм корректен, но скорость, его как мне кажется, не достаточна. Что же произойдет, если откомпилировать код с вызовом стандартной strlen в Debug? – Будет вызвана библиотечная функция strlen, как и ожидается, но написанная человеком вручную на assembler.
Таблица 1 – время работы бенча strlen в секундах (MS VS 2019 community, C++ cl version: 19.22.27905)
Большой блок, 1K | Большой блок, 1K, *вызов strlen | Малый блок, 10 элементов | Малый блок, 10 элементов, *вызов strlen | |
---|---|---|---|---|
Debug, x86 | 7.25 | 7.25 | 3.06 | 3.06 |
Release, x86 | 9.0 | 3.9 | 0.15 | 0.12 |
Debug, x64 | 6.0 | 6.0 | 3.4 | 3.4 |
Release, x64 | 8.5 | 2.3 | 0.15 | 0.11 |
* вынуждаем компилятор вызвать библиотечную функцию strlen
Таким образом можно сделать вывод, что подстановка компилятором MS VS побайтового сравнения неэффективна даже на строках малого размера, а на строках большого, Debug опережает Release!
Строка компилируется
Debug в: вызов библиотечной функции strlen;
Release в: побайтовое сравнение.
Если ее закомментировать и написать
мы вынудим компилятор всегда вызывать библиотечную функцию.
За счет чего достигнуто ускорение библиотечной функции перед побайтовым сравнением в 2,3 раза (для Release, x86, 1k)?
За счет сравнения не по одному байту, а сразу по 4. Вся магия здесь:
Можно ли сделать быстрее, используя векторные инструкции современных процессоров? Попробуем.
Пользуясь Intel Intrinsics guide, находим интринсик _mm_cmpistri SSE4.2, предназначенный как раз для работы со строками. На вход подается 2 вектора длины 128 бит и маска операций. В качестве маски используем: _SIDD_UBYTE_OPS=0 – тип данных, _SIDD_CMP_EQUAL_EACH=8 – операция побайтового равнения, а сравнивать будем с нулевым вектором. Возвращаемым значением будет число первых попарно неравных элементов (то есть если элемент совпал при проверке слева-направо счет останавливается, буду рад, если кто-то подтвердит поведение).
Служит для выравнивания адреса загружаемой строки, адрес нужен кратным 16 для работы большинства SSE инструкций. Для инструкции pcmpistri, используемой нами, выравнивание строго не нужно, исключение доступа не будет вызвано.
Интринсики
Однако, выравнивание по 16 полезно и в нашем случае, дает небольшой прирост быстродействия и так мы точно уверены, что цикл чтения по 16 байт не выйдет на потенциально не аллоцированную страницу (страница памяти по 4K).
«Добирает» размер строки, если обнаружен ее конец (так как я не до конца уверен в алгоритме работы _mm_cmpistri).
удален после комментария picul, что дало прирост на строках небольшого размера.
Сделали ли мы самую быструю strlen? – К сожалению, нет, ребята с https://www.strchr.com/sse2_optimised_strlen сделали еще быстрее и не используя SSE4.2.
Таблица 2 – время работы бенча strlen в секундах (Release)
Число символов | MS побайтовое сравнение | MS strlen | SSE 4.2 | SSE 2 |
---|---|---|---|---|
10, x86 | 0.15 | 0.12 | 0.12 | 0.125 |
1K, x86 | 9.0 | 3.9 | 1.65 | 1.42 |
10, x64 | 0.15 | 0.11 | 0.08 | 0.1 |
1K, x64 | 8.5 | 2.3 | 1.6 | 1.32 |
Мне кажется, MS-у всегда нужно вызывать библиотечную strlen, а не делать подстановку побайтового сравнения.
UPD.
Добавлен тест x64.
Удален последний цикл в strlen_SSE4
В предыдущей главе мы практически без объяснений использовали операцию sizeof, которая дает нам размер объектов в байтах Функция strlen( ) позволяет определять длину строки числом символов. Поскольку для размещения одного символа в памяти отводится 1 байт, можно было бы предположить, что в результате применения любой из этих двух операций к одной строке будет получен одинаковый результат. Оказывается, это не так. Давайте немного изменим нашу предыдущую программу (добавим к ней несколько строк), и тогда мы поймем, в чем дело.
#define PRAISE » Вот это да, какое великолепное имя!»
printf(» Как вас зовут? «);
printf(» Ваше имя состоит из %d букв и занимает %d ячеек памяти. «,
strlen (name), sizeof name);
printf(» Хвалебная фраза состоит из %d букв», strlen (PRAISE));
printf(» и занимает %d ячеек памяти. «, sizeof PRAISE);
Заметим, что случайно мы воспользовались двумя методами для обработки длинных операторов printf(). В первом случае мы, записав один оператор печати в двух строках программы. Мы сделали это, поскольку разрешается разбивать строку между аргументами, но не посередине строки. В другом случае использовались два оператора printf() для печати одной строки; мы указали символ «новая строка» ( ) только во втором из них. Представленный ниже результат работы данной программы поможет понять подобную ситуацию:
Привет, Перки. Вот это да, какое великолепное имя!
Ваше имя состоит из 5 букв и занимает 50 ячеек памяти.
Хвалебная фраза состоит из 35 букв и занимает 36 ячеек памяти.
Давайте посмотрим, в чем дело. Массив name занимает 50 ячеек памяти, и именно об этом сообщает операция sizeof. Но для хранения имени Перки требуются только первые пять ячеек, и как раз об этом нас информирует функция strlen( ). В шестой ячейке массива name содержится нуль-символ, и его появление служит сигналом для функции strlen( ) прекратить подсчет символов
РИС.4.4. Распознавание функцией strlen( ) конца строки
При переходе к обработке константы PRAISE обнаруживается, что функция strlen( ) опять дает нам точное число символов (включая пробелы и знаки пунктуации) в строке. Результат операции sizeof оказывается на единицу большим, поскольку при этом учитывается и «невидимый» нуль-символ, помещенный в конец строки. Мы не указываем компилятору, какой объем памяти он должен отвести для размещения всей фразы, он сам подсчитывает число символов между кавычками.
Читайте также
6.13.3 Версия, длина заголовка и длина датаграммы
6.13.3 Версия, длина заголовка и длина датаграммы В настоящее время используется четвертая версия IP (версия «Следующее поколение» имеет номер 6).Длина заголовка измеряется в 32-разрядных словах. Если не нужны дополнительные варианты, можно ограничиться длиной заголовка в 5
Длина дуги
Длина дуги С помощью команды DIMARC создается размер длины дуги, указывающий расстояние вдоль дуги или дугового сегмента полилинии (рис. 11.14). Чтобы отличать эти размеры от линейных и угловых, для размеров длины дуги по умолчанию отображается символ дуги. Команда вызывается
Длина дуги
Длина дуги С помощью команды DIMARC создается размер длины дуги, указывающий расстояние вдоль дуги или дугового сегмента полилинии (рис. 11.14). Чтобы отличать эти размеры от линейных и угловых, для размеров длины дуги по умолчанию отображается символ дуги. Команда
Особенности кодирования литеральных символов и пар расстояние/длина
Особенности кодирования литеральных символов и пар расстояние/длина В предыдущих разделах ничего не было сказано о небольшом нюансе реализации алгоритма: как в процессе считывания сжатых данных отличить литеральный символ от кода расстояние/длина? В конце концов, не
Строки
Длина дуги
Пример 9-15. Длина переменной
Длина дуги
Длина дуги С помощью команды DIMARC создается размер длины дуги, указывающий расстояние вдоль дуги или дугового сегмента полилинии (рис. 10.10). Чтобы эти размеры отличались от линейных и угловых, для размеров длины дуги по умолчанию показан символ дуги. Команда вызывается из
2.5 Строки
2.5 Строки Строка есть последовательность символов, заключенная в двойные кавычки: «. ». Строка имеет тип «массив символов» и класс памяти static (см. #4 ниже), она инициализируется зданными символами. Все строки, даже если они записаны одинково, различны. Компилятор
Какова длина второго имени?
Какова длина второго имени? Как бы стеки не заставили нас забыть, что кроме излюбленных специалистами по информатике примеров имеются структуры данных, тесно связанные с объектами реальной жизни. Вот забавный пример, взятый из почты форума Риски (Risks) (группа новостей Usenet
Строки
Строки Класс STRING описывает символьные строки. Он имеет специальный статус, поскольку нотация допускает манифестные строковые константы, обозначающие экземпляры STRING.Строковая константа записывается в двойных кавычках, например,»ABcd Ef
какой заголовочный файл C ++ объявляет strlen?
Какая библиотека делает strlen() принадлежать?
Я попробовал следующий код, и он работает:
Я поставил str равен 3 и дать правильный ответ 3.
Почему это работает без включения строки библиотеки или cstring?
Должен ли я включить cstring или строку там? string.h?
Решение
К какой библиотеке принадлежит strlen ()? Это относится к cstring? или строка?
Ни. cstring а также string не библиотеки, они есть заголовочные файлы которые определяют интерфейс к различным функциям и классам.
Настоящий реализация из strlen функция находится в стандартной библиотеке C (иначе libc или же CRT на определенных платформах). Обычно это связано с вашим исполняемым файлом во время ссылки.
Почему это работает без включения строки библиотеки или cstring?
В вашем конкретном компиляторе и тулчейне так получилось, что заголовочный файл включает в себя в это, что означает, что любой код, который включает первое, также получает второе бесплатно. Это детали реализации и на него не следует полагаться — если вы компилируете свой код с помощью другого компилятора, вы можете внезапно оказаться в море ошибок компилятора.
Надо также включить Вот; даже если это не требуется для вашего конкретного компилятора, это может быть необходимо для других компиляторов.
Другие решения
Чтобы использовать strlen (), вам нужно включить заголовочный файл cstring.
Это был ответ, который я искал, но не нашел прямого ответа здесь.
Функция strlen () объявлена в заголовочном файле string.h
Эта программа напечатает значение 11, которое является длиной строки «Hello World». Символьные строки хранятся в массиве типа данных, называемого char. Конец строки находится путем поиска первого нулевого символа в массиве.
Возвращаемое значение функции strlen ()?
Это определение strlen, которое я вытащил.
Функция strlen () считает количество символов в данной строке и возвращает целочисленное значение. Останавливает счет персонажа, когда найден нулевой символ.
Теперь, по моему мнению, strlen для «kshitij» должен быть = 7, т.е. не включая нулевой символ, потому что функция перестает считать, как и когда она встречает нулевой символ.
Поэтому, если я хочу напечатать слово «kshitij» и его обратное столько раз, сколько букв в слове, то правильный код должен быть.
соответственно это обеспечивает достаточно правильный вывод (кроме пробелов я не понимаю)
теперь мне было интересно узнать, что он напечатает, если я это сделаю:
который, по моему мнению, не должен выдавать последнюю букву «j», но я вижу, что она выдает тот же результат, но на 1 интервал меньше, чем раньше.
Точно так же я пытался:
Со всем этим на моей тарелке, я чувствую, что strlen функция также должна считать нулевой символ strlen (a)= 8 (в том числе ‘\0’ ), но тогда я вижу только 7 выходов в окне вывода.
Это заставляет меня задуматься о том, считает ли функция strlen нулевой символ или нет, и если да, то она должна показывать его как пробел в окне вывода. Я не могу понять полную концепцию, любая помощь приветствуется?
Я новичок в программировании, пожалуйста, успокойся на мне. Спасибо :).
Решение
Дополнительный интервал, который вы видите, это тот нулевой символ. В некоторых операционных системах печать нулевого символа не имеет видимого эффекта, но в вашей системе это, очевидно, печатает пробел.
Другие решения
Идея сделать цикл с казнями в исполнении Len