Поскольку байт '\ 0' должен преобразовываться в широкий нулевой символ независимо от состояния сдвига (5.2.1.2 многобайтовых символов), а функция mbrtowc()
указана для сброса состояния сдвига при преобразовании в широкий нулевой символ (7.24.6.3.2 / 3 функция mbrtowc), вызов mbrtowc( NULL, "", 1, ps)
сбросит состояние сдвига, сохраненное в mbstate_t
, указанном ps
. И если mbrtowc( NULL, "", 1, NULL)
вызывается для использования внутреннего объекта mbstate_t
библиотеки, он будет сброшен в исходное состояние. В конце ответа приводятся ссылки на соответствующие биты стандарта.
Я ни в коем случае не особенно разбираюсь в стандартных многобайтовых функциях преобразования C (мой опыт с такими вещами заключался в использовании Win32 API для преобразования).
Если mbrtowc()
обрабатывает «неполный символ», который обрезается на 0 байтов, он должен возвратить (size_t)(-1)
, чтобы указать недопустимый многобайтовый символ (и, таким образом, обнаружить опасную ситуацию, которую вы описываете). В этом случае состояние преобразования / сдвига не определено (и я думаю, что вы в основном используете эту строку). Многобайтовая «последовательность», в которой была предпринята попытка преобразования, но содержащая '\0'
, недействительна и будет действительна для последующих данных. Если '\0
'не должен был быть частью преобразованной последовательности, то он не должен был быть включен в число байтов, доступных для обработки.
Если вы находитесь в ситуации, когда вы можете получить дополнительные, последующие байты для частичного многобайтового символа (скажем, из сетевого потока), n
, который вы передали для частичного многобайтового символа, не должен включать 0 байт, так что вы получите (size_t)(-2)
возвращено. В этом случае, если вы передадите '\0'
в середине частичного преобразования, вы потеряете тот факт, что произошла ошибка, и в качестве побочного эффекта сбросьте используемое состояние mbstate_t
(независимо от того, ваше это или внутренний используется потому, что вы передали NULL-указатель для ps
). Я думаю, что я в сущности повторяю ваш вопрос здесь.
Однако я думаю, что можно обнаружить и обработать эту ситуацию, но, к сожалению, она требует отслеживания какого-то состояния самостоятельно:
#define MB_ERROR ((size_t)(-1))
#define MB_PARTIAL ((size_t)(-2))
// function to get a stream of multibyte characters from somewhere
int get_next(void);
int bar(void)
{
char c;
wchar_t wc;
mbstate_t state = {0};
int in_partial_convert = 0;
while ((c = get_next()) != EOF)
{
size_t result = mbrtowc( &wc, &c, 1, &state);
switch (result) {
case MB_ERROR:
// this multibyte char is invalid
return -1;
case MB_PARTIAL:
// do nothing yet, we need more data
// but remember that we're in this state
in_partial_convert = 1;
break;
case 1:
// output the competed wide char
in_partial_convert = 0; // no longer in the middle of a conversion
putwchar(wc);
break;
case 0:
if (in_partial_convert) {
// this 'last' multibyte char was mal-formed
// return an error condidtion
return -1;
}
// end of the multibyte string
// we'll handle similar to EOF
return 0;
}
}
return 0;
}
Может быть, не идеальная ситуация, но я думаю, что это показывает, что она не полностью сломана, поэтому ее невозможно использовать.
Стандарты цитирования:
5.2.1.2 Многобайтовые символы
Многобайтовый набор символов может иметь зависящее от состояния кодирование, в котором
каждая последовательность многобайтовых символов
начинается в начальном состоянии сдвига и
входит в другой языковой сдвиг
состояния, когда конкретный многобайтовый
символы встречаются в
последовательность. В то время как в начальной смене
состояние, все однобайтовые символы
сохранить их обычную интерпретацию и
не меняйте состояние сдвига.
интерпретация для последующих байтов в
последовательность является функцией
текущее состояние сдвига.
Байт со всеми нулевыми битами должен интерпретироваться как нулевой символ
не зависит от состояния сдвига.
- Байт со всеми нулевыми битами не должен появляться во втором или последующих
байты многобайтового символа.
7.24.6.3.2 / 3 Функция mbrtowc
Если соответствующий широкий символ
нулевой широкий символ, результирующий
описанное состояние является начальным
состояние преобразования