#c
#c
Вопрос:
Возможно ли определить размер строки в байтах в C?
Я пытаюсь убедиться, что строки JSON, встроенные в C, не превышают ограничение в размере 1 МБ, прежде чем передавать их запрашивающему приложению. Я не знаю строки во время компиляции.
Я читал, что это просто strlen * sizeof( char )
; но я этого не понимаю, потому что я читал в другом месте, что UTF-8 может содержать символы размером до четырех байт и sizeof( char )
всегда равен единице.
Я, вероятно, неправильно понимаю что-то основное.
Если массив символов выделяется как char JSON[1048576]
, выделяет ли это столько символов или байтов? Если это байты, то до тех пор, пока snprintf
при записи в массив JSON используется что-то подобное, гарантирует ли это, что его размер никогда не может превышать 1 МБ, даже если в этом массиве были символы, превышающие один байт?
Спасибо.
Комментарии:
1. Один
char
гарантирует, что его размер равен 1 байту.2. @Rohan Bari Спасибо. Я наткнулся на сайт, который утверждает, что вычисляет размер байта любой строки в C и показывает пример
i ♥ u
и говорит, что это 7 байт. Если сердце равно 3 байтам, какchar
гарантировать, что оно будет одним байтом или займет 3 символа?3. Да, он занимает до 3 символов. Смотрите демонстрацию.
4. @RohanBari Спасибо. Я не думал, что это так просто. Я заглянул в
<string.h>
заголовок и, поскольку использую MinGW-W64, в нем есть только одна строка, которая используетstrlen
функцию Windows, и они заявляют, что «strlen интерпретирует строку как однобайтовую символьную строку, поэтому ее возвращаемое значение всегда равно количеству байтов, даже если строка содержит многобайтовые символы.» Это то, чего я не понимал.
Ответ №1:
Поскольку вам нужно ограничение размера 1MB
, а не ограничение длины строки как таковое, вы можете просто использовать strlen(json_str)
. При условии, что ваша строка json завершается нулем, ''
.
Если вы выделите char JSON[1048576]
это, вы получите массив с таким количеством байтов. И snprintf(JSON, 1048576, "<json string>", ...)
гарантирует, что вы никогда не переполните свой массив.
Однако это не гарантирует, что ваша строка является допустимой строкой utf-8, поскольку последний символ может быть многобайтовым символом, который разделяется посередине.
C — char
это не то же самое, что символ utf-8. В C char
по определению 1 байт, но в utf-8 визуальный символ, который вы хотите, например, сердечко в вашем комментарии, может быть представлен несколькими байтами данных. Один байт дает вам 256 различных значений, а поскольку для кодирования многих из них требуется более 256 символов Юникода, требуется более одного байта. Разработчики utf-8 были умны, поэтому первые 127 символов могут быть закодированы с использованием всего одного байта, и если используются только эти символы, будут действительны как utf-8, так и ascii.
Комментарии:
1. Спасибо за объяснение. Эта часть о разрыве на части многобайтового символа — ошибка. Вы случайно не знаете, как это следует обрабатывать? Если
strlen
размер JSON превышает 1 МБ, я экранировал все двойные кавычки и передавал их по частям как обычную строку и объединял их в запрашивающем приложении. перед попыткой синтаксического анализа как JSON. Даже если разрыв был на однобайтовом символе, в моем случае это был бы недопустимый JSON, поскольку это только часть полной строки JSON. Я предполагаю, что в многобайтовом сценарии после конкатенации он все равно будет успешно проанализирован?2. Забавно, тоже, в некотором смысле, потому что у меня все было наоборот, думая, что
strlen
это длина в символах независимо от размера байта. Вместоstrlen
этого возвращает байты, и никто не знает, сколько символов в этих байтах.3. Если JSON может содержать UTF-8, то вам все равно не следует использовать
strlen
. Вам придется использовать многобайтовые строки, функции с расширенными символами, преобразования и т. Д. Я бы сказал, что обработка UTF-8, вероятно, является продвинутой темой.