Размер строки в байтах

В программировании: строковый тип (англ. string — «нить, вереница») — тип данных, значениями которого является произвольная последовательность (строка) символов алфавита. Каждая переменная такого типа (строковая переменная) может быть представлена фиксированным количеством байтов либо иметь произвольную длину.

Содержание

Представление в памяти [ править | править код ]

Некоторые языки программирования накладывают ограничения на максимальную длину строки, но в большинстве языков подобные ограничения отсутствуют. При использовании Unicode каждый символ строкового типа может требовать двух или даже четырёх байтов для своего представления.

Основные проблемы в машинном представлении строкового типа:

  • строки могут иметь достаточно существенный размер (до нескольких десятков мегабайтов);
  • изменяющийся со временем размер — возникают трудности с добавлением и удалением символов.

В представлении строк в памяти компьютера существует два принципиально разных подхода.

Представление массивом символов [ править | править код ]

В этом подходе строки представляются массивом символов; при этом размер массива хранится в отдельной (служебной) области. От названия языка Pascal, где этот метод был впервые реализован, данный метод получил название Pascal strings.

Слегка оптимизированным вариантом этого метода является т. н. формат c-addr u (от англ. character-aligned address + unsigned number ), применяемый в Форте. В отличие от Pascal strings, здесь размер массива хранится не совместно со строковыми данными, а является частью указателя на строку.

Преимущества [ править | править код ]

  • программа в каждый момент времени содержит сведения о размере строки, поэтому операции добавления символов в конец, копирования строки и собственно получения размера строки выполняются достаточно быстро;
  • строка может содержать любые данные;
  • возможно на программном уровне следить за выходом за границы строки при её обработке;
  • возможно быстрое выполнение операции вида «взятие N-ого символа с конца строки».

Недостатки [ править | править код ]

  • проблемы с хранением и обработкой символов произвольной длины;
  • увеличение затрат на хранение строк — значение «длина строки» также занимает место и в случае большого количества строк маленького размера может существенно увеличить требования алгоритма к оперативной памяти;
  • ограничение максимального размера строки. В современных языках программирования это ограничение скорее теоретическое, так как обычно размер строки хранится в 32-битовом поле, что даёт максимальный размер строки в 4 294 967 295 байт (4 гигабайта);
  • при использовании алфавита с переменным размером символа (например, UTF-8), в размере хранится не количество символов, а именно размер строки в байтах, поэтому количество символов необходимо считать отдельно.

Метод «завершающего байта» [ править | править код ]

Второй метод заключается в использовании «завершающего байта» [1] [2] . Одно из возможных значений символов алфавита (как правило, это символ с кодом 0) выбирается в качестве признака конца строки, и строка хранится как последовательность байтов от начала до конца. Есть системы, в которых в качестве признака конца строки используется не символ 0, а байт 0xFF (255) или код символа «$».

Метод имеет три названия — ASCIIZ (или asciz, символы в кодировке ASCII с нулевым завершающим байтом), C-strings (наибольшее распространение метод получил именно в языке Си) и метод нуль-терминированных строк.

Читайте также  Проектор для сцены дворца культуры

Преимущества [ править | править код ]

  • отсутствие дополнительной служебной информации о строке (кроме завершающего байта);
  • возможность представления строки без создания отдельного типа данных;
  • отсутствие ограничения на максимальный размер строки;
  • экономное использование памяти;
  • простота получения суффикса строки;
  • простота передачи строк в функции (передаётся указатель на первый символ);

Недостатки [ править | править код ]

  • долгое выполнение операций получения длины и конкатенации строк;
  • отсутствие средств контроля за выходом за пределы строки, в случае повреждения завершающего байта возможность повреждения больших областей памяти, что может привести к непредсказуемым последствиям — потере данных, краху программы и даже всей системы;
  • невозможность использовать символ завершающего байта в качестве элемента строки.
  • невозможность использовать некоторые кодировки с размером символа в несколько байт (например, UTF-16), т.к. во многих таких символах, например Ā (0x0100), один из байтов равен нулю (в то же время, кодировка UTF-8 свободна от этого недостатка).

Использование обоих методов [ править | править код ]

В таких языках, как, например, Оберон, строка размещается в массиве символов определённой длины, причём её конец обозначается нулевым символом. По умолчанию, весь массив заполнен нулевыми символами. Такой способ позволяет объединить многие преимущества обоих подходов, а также избежать большинство их недостатков.

Представление в виде списка [ править | править код ]

Языки Erlang [3] , Haskell [4] , Пролог [5] используют для строкового типа список символов. Этот метод делает язык более «теоретически элегантным» за счёт соблюдения ортогональности в системе типов, но приносит существенные потери быстродействия.

Реализация в языках программирования [ править | править код ]

  • В первых языках программирования вообще не было строкового типа; программист должен был сам строить функции для работы со строками того или другого типа.
  • В Си используются нуль-терминированные строки с полным ручным контролем со стороны программиста.
  • В стандартном Паскале строка выглядит как массив из 256 байтов; первый байт хранил длину строки, в остальных хранится её тело. Таким образом, длина строки не может превышать 255 символов. В Borland Pascal 7.0 также появились строки «а-ля Си» — очевидно, из-за того, что в число поддерживаемых платформ вошла Windows.
  • В Object Pascal и C++ STL строка является «чёрным ящиком», в котором выделение/высвобождение памяти происходит автоматически — без участия программиста. При создании строки память выделяется автоматически; как только на строку не останется ни одной ссылки, память возвращается системе. Преимущество этого метода в том, что программист не задумывается над работой строк. С другой стороны, программист имеет недостаточный контроль над работой программы в критичных к скорости участках; также трудно реализуется передача таких строк в качестве параметра в DLL. Также Object Pascal автоматически следит, чтобы в конце строки был символ с кодом 0. Поэтому если функция требует на входе нуль-терминированную строку, для конвертации надо просто написать PAnsiChar(строковая_переменная) или PWideChar(строковая_переменная) (для Pascal), переменная.c_str() (для Builder/STL).
  • В C# и других языках со сборкой мусора строка является неизменяемым объектом; если строку нужно модифицировать, создаётся другой объект. Этот метод медленный и расходует немало временной памяти, но хорошо сочетается с концепцией сборки мусора. Преимущество этого метода в том, что присваивание происходит быстро и без дублирования строк. Также имеется некоторый ручной контроль над конструированием строк (в Java, например, через классы StringBuffer и StringBuilder ) — это позволяет уменьшить количество выделений и высвобождений памяти и, соответственно, увеличить скорость.
  • В некоторых языках (например, Standard ML) кроме этого, есть дополнительный модуль для обеспечения ещё большей эффективности — «подстрока» (SubString). Его использование позволяет выполнять операции над строками без копирования их тел посредством манипулирования индексами начала и конца подстроки; физическое копирование происходит лишь при необходимости преобразовании подстрок в строки.
Читайте также  Ростелеком тариф твой продвинутый список каналов

Операции [ править | править код ]

Представление символов строки [ править | править код ]

До последнего времени один символ всегда кодировался одним байтом (8 двоичных битов; применялись также кодировки с 7 битами на символ), что позволяло представлять 256 (128 при семибитной кодировке) возможных значений. Однако для полноценного представления символов алфавитов нескольких языков (многоязыковых документов, типографских символов — несколько видов кавычек, тире, нескольких видов пробелов и для написания текстов на иероглифических языках — китайском, японском и корейском) 256 символов недостаточно. Для решения этой проблемы существует несколько методов:

  • Переключение языка управляющими кодами. Метод не стандартизирован и лишает текст самостоятельности (то есть последовательность символов без управляющего кода в начале теряет смысл); использовался в некоторых ранних русификациях ZX-Spectrum и БК.
  • Использование двух или более байт для представления каждого символа (UTF-16, UTF-32). Главным недостатком этого метода является потеря совместимости с предыдущими библиотеками для работы с текстом при представлении строки как ASCIIZ. Например, концом строки должен считаться уже не байт со значением 0, а два или четыре подряд идущих нулевых байта, в то время как одиночный байт «0» может встречаться в середине строки, что сбивает библиотеку «с толку».
  • Использование кодировки с переменным размером символа. Например, в UTF-8 часть символов представляется одним байтом, часть двумя, тремя или четырьмя. Этот метод позволяет сохранить частичную совместимость со старыми библиотеками (нет символов 0 внутри строки и поэтому 0 можно использовать как признак конца строки), но приводит к невозможности прямой адресации символа в памяти по номеру его позиции в строке.

Я вижу, что str.length возвращает длину в байтах, почему sizeof (str) не возвращает то же самое?

Есть ли альтернатива в c ++ команде c, которая является strlen (str)? Какова альтернатива этой Coomand в C ++?

Когда я использую winsock в функции send, я возвращаю длину в байтах. Что я должен использовать?
str.length? Или sizeof (ул)? Pr что-то еще? Потому что я вижу, что они дают разные результаты.

Решение

sizeof возвращает размер структуры данных, а не размер содержащихся данных.

length () возвращает длину строки, содержащейся в str, и является функцией, которую вы хотите

Это может показаться странным, потому что sizeof (char [30]) равен 30, но это потому, что размер структуры данных равен 30, и останется 30 независимо от того, что вы в него положите

Строка на самом деле является чрезвычайно сложной структурой, но предположим, что это был простой класс с указателем и длиной

тогда sizeof (строка) вернет:

Размер указателя на символ *, возможно, но не обязательно 4

плюс размер int, возможно, но не обязательно 4

Таким образом, вы можете получить значение 8. То, что значение данных или длины не влияет на размер структуры.

Другие решения

sizeof() на самом деле не предназначен для использования в строковом классе. Класс string не хранит ТОЛЬКО строковые данные; не было бы никакой разницы между его данными и строкой в ​​стиле C; в нем есть и другие вещи, которые сбрасывают sizeof (). Чтобы получить фактическую длину символов в строке, используйте str.length() ,
Не используйте C strlen () для строкового объекта C ++. Также не используйте sizeof (). использование .length().

Читайте также  Программа индекс производительности windows 10

std::string в C ++ создается экземпляр как указатель на строковый объект, поскольку строка может иметь различную длину. Какие sizeof() возвращается размер указателя на строковый объект (который на 32-битной машине, вероятно, будет 4 )

оператор sizeof() возвращает размер данного типа или объекта в байтах. «Type version» довольно просто понять, но с «Object version» вам нужно помнить одну вещь:

sizeof() смотрит только на определение типа и выводит общий размер из размера и количества его членов (как правило, полиморфный и несколько унаследованных типов могут иметь дополнительные «скрытые» члены).

Другими словами, давайте предположим, что у нас есть:

Как вы можете подозревать, sizeof(A) вернет 8 (так как указатель имеет 4-байтовый тип в большинстве 32-битных систем). Но когда вы делаете что-то вроде этого:

sizeof(a_1) все равно вернет 8. Это потому, что память, выделенная новым и указанная членом А, не «принадлежит» этому объекту.

Как видно из названия, мой вопрос заключается в том, как получить размер строки в C , Это хорошо использовать sizeof Если я’мы объявили это (строку) в функции без malloc в этом? Или, если яВы объявили это как указатель? Что делать, если я инициализировал это с malloc ? Я хотел бы получить исчерпывающий ответ.

Мне нравится использовать:

Это даст вам размер буфера в байтах. Вы можете использовать это с snprintf () может помочь:

Ура! Функция: size_t strlen (const char *s)

StrLen, Размер определяется завершающим нулевым символом, поэтому переданная строка должна быть действительной.

Если вы хотите получить размер буфера памяти, который содержит вашу строку, и у вас есть указатель на нее:

Если это динамический массив (созданный с помощью malloc), невозможно получить его размер, так как компилятор не ‘не знаю, на что указывает указатель. (Проверь это)Если это статический массив, вы можете использовать sizeof чтобы получить его размер.

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

sizeof() затем char *str а также char str[] вернет разные ответы. char str[] вернет длину строки (включая терминатор строки), в то время как char *str вернет размер указателя (отличается в зависимости от компилятора).

strlen чтобы получить длинустрока с нулевым символом в конце.

sizeof возвращает длинумассив не строка Если оно’указатель ( char *s ), а не массив ( char s[] ) это победилоЭто не сработает, так как он вернет размер указателя (обычно 4 байта в 32-битных системах). Я считаю, что массив будет передан или возвращен как указатель, так что вы ‘потерял способность использовать sizeof проверить размер массива.

Так,только если строка охватывает весь массив (например. char s[] = "stuff" ), будет использовать sizeof длястатически определен массив возвращает то, что вы хотите (и будет быстрее, чемчтобы найти нулевой терминатор, нужно пройти через цикл (если последний символ является нулевым, вам необходимо вычесть 1). Если это не такт весь массив, он выиграетвернуть то, что вы хотите.

Альтернативой всему этому является сохранение размера строки.

Ссылка на основную публикацию
Adblock
detector