Термин «строка фиксированной ширины» обычно относится к чему-то совершенно другому.
Строка фиксированной ширины с N
- это строка из ровно N
символов, где все символы N
гарантированно инициализируются.Если вы хотите представить более короткую строку, вы должны дополнить ее нулевыми символами в конце.Вы должны добавить столько нулевых символов, сколько необходимо, чтобы использовать все символы N
.Обратите внимание, что если вам нужно сохранить строку длины точно N
, строка фиксированной ширины будет иметь без нулевого символа в конце.Т.е. в общем случае строки фиксированной ширины не завершаются нулями!
Какова цель этого?Цель этого - сохранить 1 символ при сохранении строки максимально возможной длины.Если вы используете строки фиксированной ширины шириной N
, то вам нужно ровно N
символов для представления строки длиной N
.Сравните это с обычными строками с нулевым символом в конце, для которых потребуется символ N + 1
(дополнительный символ для терминатора нуля).
Почему в конце он дополняется нулями?Он дополняется нулями для упрощения лексикографического сравнения строк фиксированной ширины.Вы просто сравниваете все N
символов, пока не достигнете разницы.Обратите внимание, что можно использовать абсолютно любой символ для дополнения строки фиксированной ширины до полной длины.Просто убедитесь, что вы получаете правильный лексикографический порядок.Использование нулевого символа для заполнения - хороший выбор.
Когда это полезно?Очень редко.Экономия, обеспечиваемая строками фиксированной ширины, редко важна при обработке общих строк: они слишком малы и происходят только в тех случаях, когда строка использует всю ширину.Но они могут пригодиться в некоторых конкретных случаях.
Откуда все это?Классическим примером «строки фиксированной ширины» является поле имени файла шириной 14 символов в какой-то старой версии файловой системы Unix.Он был представлен массивом из 14 символов, и было использовано представление с фиксированной шириной.В то время было важно сохранить 1 символ в имени файла полной длины (все 14 символов).
Теперь strncpy
.Функция strncpy
была специально введена для инициализации этих 14-символьных полей имени файла в этой файловой системе.Функция strncpy
была специально создана для генерации правильной строки фиксированной ширины: она выполняет преобразование строки с нулевым окончанием в строку фиксированной ширины.К сожалению, ему было дано вводящее в заблуждение имя, поэтому многие люди сегодня принимают его за «безопасную» функцию копирования строк с нулевым символом в конце.Последнее является совершенно неверным пониманием цели и функциональности strncpy
.
Использование строковых литералов для представления строк фиксированной ширины (как в вашем примере) не очень хорошая идея, поскольку строковые литералы всегда добавляют нулевой символв конце строки фиксированной ширины не обязательно делают это.Вот как набор строк фиксированной ширины может быть инициализирован в программе на Си
char fw_string1[7] = { 'T', 'h', 'i', 's', ' ', 'i', 's' };
char fw_string2[7] = { 's', 't', 'r', 'i', 'n', 'g' };
char fw_string3[7] = { 'H', 'e', 'l', 'l', 'o' };
Все массивы имеют одинаковое количество элементов - 7. Обратите внимание, что первая строка не заканчивается на ноль, аостальные заполнены нулями.Преобразование «обычной» строки в строку фиксированной ширины будет выглядеть следующим образом:
char fw_string4[7];
strncpy(fw_string4, "Hi!", 7);
В этом случае функция strncpy
используется именно для того, для чего она предназначена.
Помните также, что кроме функции преобразования strncpy
стандартная библиотека практически не предоставляет средств для работы со строками фиксированной ширины.В основном вы должны рассматривать их как необработанные массивы символов и выполнять любые операции более высокого уровня вручную.Большинство основных операций будут естественным образом реализованы функциями из группы mem...
.memcmp
, для одного примера, осуществит сравнение.
P.S. На самом деле, принимая во внимание комментарий caf, в языке C можно использовать строковые литералы для инициализации строк фиксированной ширины, поскольку язык C позволяет инициализатору литерала быть на один символ длиннее массива (т.е. в C это нормально, если завершающий ноль делает не вписывается в массив). Таким образом, вышесказанное можно эквивалентно переписать как
char fw_string1[7] = "This is";
char fw_string2[7] = "string";
char fw_string3[7] = "Hello";
Обратите внимание, что в этом случае fw_string1
по-прежнему не заканчивается на ноль.