<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://camokathomelab.servebeer.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=UTF-8</id>
	<title>UTF-8 - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://camokathomelab.servebeer.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=UTF-8"/>
	<link rel="alternate" type="text/html" href="https://camokathomelab.servebeer.com/mediawiki/index.php?title=UTF-8&amp;action=history"/>
	<updated>2026-07-16T02:31:52Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://camokathomelab.servebeer.com/mediawiki/index.php?title=UTF-8&amp;diff=13261&amp;oldid=prev</id>
		<title>imported&gt;Felex67: дополнение: пример кода на языке C.</title>
		<link rel="alternate" type="text/html" href="https://camokathomelab.servebeer.com/mediawiki/index.php?title=UTF-8&amp;diff=13261&amp;oldid=prev"/>
		<updated>2026-02-25T10:23:59Z</updated>

		<summary type="html">&lt;p&gt;дополнение: пример кода на языке C.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;UTF-8&amp;#039;&amp;#039;&amp;#039; (от {{lang-en|Unicode Transformation Format, 8-bit}} — «формат преобразования Юникода, 8-бит») — распространённый стандарт кодирования [[Набор символов|символов]], позволяющий более компактно хранить и передавать символы [[Юникод]]а, используя переменное количество байт (от 1 до 4), и обеспечивающий полную обратную совместимость с 7-битной кодировкой [[ASCII]]. Стандарт UTF-8 официально закреплён в документах RFC 3629 и ISO/IEC 10646 Annex D.&lt;br /&gt;
&lt;br /&gt;
Кодировка UTF-8 сейчас является доминирующей в веб-пространстве. Она также нашла широкое применение в [[UNIX-подобная операционная система|UNIX-подобных операционных системах]]&amp;lt;ref&amp;gt;[https://w3techs.com/technologies/overview/character_encoding/all Usage Statistics of Character Encodings for Websites, June 2011]{{ref|en}}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Формат UTF-8 был разработан [[2 сентября]] [[1992 год]]а [[Томпсон, Кен|Кеном Томпсоном]] и [[Пайк, Роб|Робом Пайком]], и реализован в [[Plan 9]]&amp;lt;ref&amp;gt;{{Cite web |url=http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt |title=Архивированная копия |access-date=2007-02-27 |archive-date=2011-03-01 |archive-url=https://web.archive.org/web/20110301051538/http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt |url-status=dead |lang=en}}&amp;lt;/ref&amp;gt;. Идентификатор кодировки в Windows — 65001&amp;lt;ref&amp;gt;{{Cite web |url=https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers |title=Code Page Identifiers — Windows applications {{!}} Microsoft Docs&amp;lt;!-- Заголовок добавлен ботом --&amp;gt; |access-date=2018-07-14 |archive-date=2019-06-16 |archive-url=https://web.archive.org/web/20190616012252/https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers |url-status=live }}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
UTF-8, по сравнению с [[UTF-16]], наибольший выигрыш в компактности даёт для текстов на [[латиница|латинице]], поскольку латинские буквы без [[Диакритические знаки|диакритических знаков]], цифры и наиболее распространённые знаки препинания кодируются в UTF-8 лишь одним байтом, и коды этих символов соответствуют их кодам в [[ASCII]].&amp;lt;ref name=&amp;quot;stringtheory&amp;quot;&amp;gt;&lt;br /&gt;
{{Cite web&lt;br /&gt;
 |url           = http://weblogs.mozillazine.org/roc/archives/2008/01/string_theory.html&lt;br /&gt;
 |title         = String Theory&lt;br /&gt;
 |author        = Well, I&amp;#039;m Back&lt;br /&gt;
 |work          = Robert O&amp;#039;Callahan&lt;br /&gt;
 |lang          = en&lt;br /&gt;
 |datepublished = 2008-03-01&lt;br /&gt;
 |access-date    = 2008-03-01&lt;br /&gt;
 |archive-url    = https://www.webcitation.org/6193EbztY?url=http://robert.ocallahan.org/2008/01/string-theory_08.html&lt;br /&gt;
 |archive-date   = 2011-08-23&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;vsem&amp;quot;&amp;gt;&lt;br /&gt;
{{Cite web&lt;br /&gt;
 |url         = http://webmastak.com/article.aspx?id=300&lt;br /&gt;
 |title       = Всем кодировкам кодировка. UTF‑8: современно, грамотно, удобно.&lt;br /&gt;
 |author      = Ростислав Чебыкин&lt;br /&gt;
 |work        = HTML и CSS&lt;br /&gt;
 |access-date  = 2009-03-22&lt;br /&gt;
 |archive-url  = https://www.webcitation.org/6193F9SrL?url=http://webmastak.com/article.aspx?id=300&lt;br /&gt;
 |archive-date = 2011-08-23&lt;br /&gt;
}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Алгоритм кодирования (сериализации) ==&lt;br /&gt;
Алгоритм кодирования в UTF-8 стандартизирован в [https://www.rfc-editor.org/rfc/rfc3629 RFC 3629] и состоит из 3 этапов:&lt;br /&gt;
&lt;br /&gt;
1. Определить количество [[Октет (информатика)|октетов]], требуемых для кодирования символа. Номер символа берётся из стандарта [[Юникод]]а.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Диапазон номеров символов&lt;br /&gt;
!Требуемое количество [[Октет (информатика)|октетов]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;00000000-0000007F&amp;lt;/code&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;00000080-000007FF&amp;lt;/code&amp;gt;&lt;br /&gt;
|2&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;00000800-0000FFFF&amp;lt;/code&amp;gt;&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;00010000-0010FFFF&amp;lt;/code&amp;gt;&lt;br /&gt;
|4&lt;br /&gt;
|}&lt;br /&gt;
Для символов [[Юникод]]а с номерами от &amp;lt;code&amp;gt;U+0000&amp;lt;/code&amp;gt; до &amp;lt;code&amp;gt;U+007F&amp;lt;/code&amp;gt; (занимающими один октет c нулём в старшем бите) кодировка UTF-8 полностью соответствует 7-битной кодировке US-ASCII.&lt;br /&gt;
&lt;br /&gt;
2. Установить старшие [[бит]]ы первого октета в соответствии с необходимым количеством октетов для кодирования символа, определённом на первом этапе:&lt;br /&gt;
* 0xxxxxxx — если для кодирования потребуется &amp;#039;&amp;#039;один&amp;#039;&amp;#039; октет;&lt;br /&gt;
* 110xxxxx — если для кодирования потребуется &amp;#039;&amp;#039;два&amp;#039;&amp;#039; октета;&lt;br /&gt;
* 1110xxxx — если для кодирования потребуется &amp;#039;&amp;#039;три&amp;#039;&amp;#039; октета;&lt;br /&gt;
* 11110xxx — если для кодирования потребуется &amp;#039;&amp;#039;четыре&amp;#039;&amp;#039; октета.&lt;br /&gt;
Если для кодирования требуется больше одного октета, то в октетах 2-4 два старших бита всегда устанавливаются равными 10&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; (10xxxxxx). Это позволяет легко отличать первый октет в потоке, от других октетов&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Количество [[Октет (информатика)|октетов]]&lt;br /&gt;
!Значащих бит&lt;br /&gt;
!Шаблон&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|7&lt;br /&gt;
|&amp;lt;code&amp;gt;0xxxxxxx&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|11&lt;br /&gt;
|&amp;lt;code&amp;gt;110xxxxx 10xxxxxx&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|16&lt;br /&gt;
|&amp;lt;code&amp;gt;1110xxxx 10xxxxxx 10xxxxxx&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|21&lt;br /&gt;
|&amp;lt;code&amp;gt;11110xxx 10xxxxxx 10xxxxxx 10xxxxxx&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
3. Установить значащие биты октетов в соответствии с номером символа [[Юникод]]а, выраженном в двоичном виде. Начать заполнение с младших битов номера символа, поставив их в младшие биты последнего октета, продолжить справа налево до первого октета. Свободные биты первого октета, оставшиеся незадействованными, заполнить нулями.&lt;br /&gt;
&lt;br /&gt;
=== Примеры кодирования ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=2|Символ&lt;br /&gt;
! Двоичный код символа&lt;br /&gt;
! UTF-8 в двоичном виде&lt;br /&gt;
! UTF-8 в шестнадцатеричном виде&lt;br /&gt;
|-&lt;br /&gt;
|[[Символ доллара|$]] || &amp;lt;code&amp;gt;U+0024&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|red|0100100}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0{{color|red|0100100}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|black|24}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[Символ цента|¢]] || &amp;lt;code&amp;gt;U+00A2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|green|10}}{{color|red|100010}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;110{{color|green|00010}} 10{{color|red|100010}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|black|C2}} {{color|black|A2}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[Символ евро|€]] || &amp;lt;code&amp;gt;U+20AC&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|blue|10}}{{color|green|0000}} {{color|green|10}}{{color|red|101100}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1110{{color|blue|0010}} 10{{color|green|000010}} 10{{color|red|101100}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|black|E2}} {{color|black|82}} {{color|black|AC}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[Хвайр|𐍈]] || &amp;lt;code&amp;gt;U+10348&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|blue|1 0000}}{{color|green|0011 01}}{{color|red|001000}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;11110{{color|#C000C0|000}} 10{{color|blue|010000}} 10{{color|green|001101}} 10{{color|red|001000}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;{{color|black|F0}} {{color|black|90}} {{color|black|8D}} {{color|black|88}}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Пример кодирования Unicode-строки в UTF-8 без предварительного просчёта длины на языке C ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#ifdef _WIN32 &lt;br /&gt;
	typedef unsigned __int8 u_int8_t;&lt;br /&gt;
	typedef unsigned __int16 u_int16_t;&lt;br /&gt;
	typedef unsigned __int32 u_int32_t;&lt;br /&gt;
	typedef unsigned __int64 u_int64_t;&lt;br /&gt;
	typedef wchar_t uchar_t;&lt;br /&gt;
#else&lt;br /&gt;
	#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
	typedef u_int16_t uchar_t;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
size_t UnicodeToUTF8(char** pDest, const uchar_t* Src, size_t SrcLen) {&lt;br /&gt;
	size_t dlen = 0;				// Длина целевой строки&lt;br /&gt;
	char* offset = *pDest = NULL	// Итератор по целевой строке&lt;br /&gt;
		, header = (char)0x80		// &amp;quot;заголовок&amp;quot; первого байта&lt;br /&gt;
		, fcap = 0b00111111;		// Вместимость первого бийта&lt;br /&gt;
	const uchar_t* src = Src		// указатель на кодируемую точку&lt;br /&gt;
		, * end = Src + SrcLen;		// Указатель на конец исходной строки&lt;br /&gt;
	uchar_t code = 0;				// Кодируемая точка&lt;br /&gt;
	u_int32_t* ibuf = NULL;			// Указатель на целевую строку представленную как беззнаковое целое 32 бита&lt;br /&gt;
	// Выделяем память, сохраняем указатель в *pDest, заодно инициализируем итератор&lt;br /&gt;
	offset = *pDest = (char*)malloc(SrcLen * 4 + 4);&lt;br /&gt;
	// Проверяем выделена ли память&lt;br /&gt;
	if (NULL != offset) {&lt;br /&gt;
		// основной цикл&lt;br /&gt;
		while (src &amp;lt; end) {&lt;br /&gt;
			/* Проверяем размерность исходного символа, если величина&lt;br /&gt;
				меньше чем 0x80U, значит его кодировать не нужно */&lt;br /&gt;
			if (*src &amp;lt; 0x80UL) {&lt;br /&gt;
				// копируем значение&lt;br /&gt;
				*(offset) = *(char*)(src);&lt;br /&gt;
			}&lt;br /&gt;
			else {&lt;br /&gt;
				// Коируем кодовую точку&lt;br /&gt;
				code = *src;&lt;br /&gt;
				// сохраняем указатель на первый байт как на беззнаковое целое 32 бита&lt;br /&gt;
				ibuf = (u_int32_t*)offset;&lt;br /&gt;
				// Обнуляем 4 байта&lt;br /&gt;
				(*ibuf) = 0UL;&lt;br /&gt;
				// Инициализируем заголовок&lt;br /&gt;
				header = (char)0x80;&lt;br /&gt;
				// выставляем вместимость первого байта&lt;br /&gt;
				fcap = 0b00111111U;&lt;br /&gt;
				/* цикл непосредственно кодирования точки в последовательность байтов */&lt;br /&gt;
				while (code) {&lt;br /&gt;
					// &lt;br /&gt;
					// сравниваем вместимость первого байта и остаток незакодированных битов&lt;br /&gt;
					if (fcap &amp;lt; code) {&lt;br /&gt;
						// вместимость не меньше остатка&lt;br /&gt;
						// копируем младшие 6 битов&lt;br /&gt;
						*ibuf |= code &amp;amp; 0b00111111UL;&lt;br /&gt;
						// копируем маркер последующего байта&lt;br /&gt;
						*ibuf |= 0x80UL;&lt;br /&gt;
						// сдвигаем все биты в более старший байт&lt;br /&gt;
						*ibuf &amp;lt;&amp;lt;= 8;&lt;br /&gt;
						// убираем закодированные 6 битов&lt;br /&gt;
						code &amp;gt;&amp;gt;= 6;&lt;br /&gt;
						// сдвигаем &amp;quot;заголовок&amp;quot; первого байта на 1 вправо&lt;br /&gt;
						header &amp;gt;&amp;gt;= 1;&lt;br /&gt;
						// уменьшаем вместимость первого байта&lt;br /&gt;
						fcap &amp;gt;&amp;gt;= 1;&lt;br /&gt;
						// инкрементируем длину целевой строки&lt;br /&gt;
						++dlen;&lt;br /&gt;
						// смещаем указатель на на итоговую строку вправо на 1 символ&lt;br /&gt;
						++offset;&lt;br /&gt;
					}&lt;br /&gt;
					else {&lt;br /&gt;
						// сохраняем заголовок и оставшиеся биты в первый байт последовательности&lt;br /&gt;
						*(u_int8_t*)ibuf |= (header | (u_int8_t)code);&lt;br /&gt;
						// обнуляем кодовую точку&lt;br /&gt;
						code = 0U;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			// Смещаем указатель на целевую строку&lt;br /&gt;
			++offset;&lt;br /&gt;
			// Смещаем указатель на исходную строку&lt;br /&gt;
			++src;&lt;br /&gt;
			// Увеличиваем показатель длины итоговой целевой строки&lt;br /&gt;
			++dlen;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	// Проверяем на ошибки, если их нет - обозначаем конец целевой строки&lt;br /&gt;
	if (dlen)&lt;br /&gt;
		*offset = &amp;#039;\0&amp;#039;;&lt;br /&gt;
	// возвращаем итоговую длину&lt;br /&gt;
	return dlen;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Алгоритм декодирования (десериализации) ==&lt;br /&gt;
Алгоритм декодирования требуется для того, чтобы преобразовать сырую последовательность октетов, в готовую для использования [[Юникод]] точку. Алгоритм состоит из 3-х этапов:&lt;br /&gt;
&lt;br /&gt;
1. Определить длину символа в октетах. Для определения длины символа, декодер UTF-8 смотрит на служебные биты (то есть те, которые сами по себе не несут полезной нагрузки, но при этом критически важны для определения длины символа в октетах.&lt;br /&gt;
&lt;br /&gt;
служебные биты в UTF-8 всегда старшие) установленные при кодировании [[Юникод]] точки в UTF-8 символ.&lt;br /&gt;
&lt;br /&gt;
если служебные биты равны 110,1110 или 11110 то текущий октет — начало символа. если служебный бит равен 0 — это ASCII символ.если служебные биты равны 10 — текущий октет является продолжением.&lt;br /&gt;
&lt;br /&gt;
2. Убрать служебные биты. Поскольку декодер UTF-8 уже определил длину символа, служебные биты больше не являются нужными, а также будут мешать этапу 3, именно поэтому декодер UTF-8 «вырезает» служебные биты из потока октетов используя побитовую операцию «И» с необходимой маской, обнуляющую служебные биты оставляя при этом биты с данными не подвергнутыми изменениям.&lt;br /&gt;
&lt;br /&gt;
3. соединить изолированные биты в [[Юникод]] точку. После того, как декодер UTF-8 убрал служебные биты, его основной задачей является соединить изолированные между собой биты в [[Юникод]] точку.&lt;br /&gt;
&lt;br /&gt;
Для этого декодер UTF-8 использует побитовый оператор «сдвига влево» (&amp;lt;&amp;lt;) который выполняет 2 операции:&lt;br /&gt;
&lt;br /&gt;
1. перемещает младшие в кодировке UTF-8 биты на их изначальную, более старшую позицию.&lt;br /&gt;
&lt;br /&gt;
2. защищает от наложений групп битов друг на друга тем, что перемещает группу битов в другое положение, оставляя свободное место для других групп битов.&lt;br /&gt;
&lt;br /&gt;
После того, как декодер UTF-8 переместил младшие биты в кодировке UTF-8 в их изначальное более старшое место, он должен поместить и младшие биты исходного символа. Для этого он использует побитовую операцию «ИЛИ» (|), которая соединяет более младшую часть исходного символа, в уже существующий октет, где есть старшая часть исходного символа.&lt;br /&gt;
&lt;br /&gt;
== Пример декодирования Unicode-строки из UTF-8 без предварительного расчёта итоговой длины на языке C ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#ifdef _WIN32 &lt;br /&gt;
	typedef unsigned __int8 u_int8_t;&lt;br /&gt;
	typedef unsigned __int16 u_int16_t;&lt;br /&gt;
	typedef unsigned __int32 u_int32_t;&lt;br /&gt;
	typedef unsigned __int64 u_int64_t;&lt;br /&gt;
	typedef wchar_t uchar_t;&lt;br /&gt;
#else&lt;br /&gt;
	#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
	typedef u_int16_t uchar_t;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
size_t UTF8ToUnicode16LE(uchar_t** Dest, char* Src, size_t SrcLen) {&lt;br /&gt;
	// Буффер для ыорматированного вывода ошибок&lt;br /&gt;
	char buf[256];&lt;br /&gt;
	u_int8_t&lt;br /&gt;
		*src = (u_int8_t*)Src,				// Указатель на обрабатываемый байт&lt;br /&gt;
		*end = (u_int8_t*)(Src + SrcLen);	// Указатель на конец исходной строки&lt;br /&gt;
	uchar_t&lt;br /&gt;
		*dest =								// Указатель на декодируемую точку целевой строки&lt;br /&gt;
		(*Dest) = (uchar_t*)malloc((end - src + 1) * sizeof(**Dest)),	// Целевая строка&lt;br /&gt;
		head;								// сюда сохраняем первый байт последовательности&lt;br /&gt;
	u_int8_t&lt;br /&gt;
		tdata = 0b00111111U,	// Маска значимых битов последующих байтов&lt;br /&gt;
		check = 0b01000000U,	// Маска проверки последующих байтов&lt;br /&gt;
		fdata,					// Маска значащих битов первого байта&lt;br /&gt;
		iter,					// Маска-итератор первого байта&lt;br /&gt;
		fshift;					// счетчик сдвига битов первого байта&lt;br /&gt;
	/* Проверяем выделилась ли память */&lt;br /&gt;
	if (dest) {&lt;br /&gt;
		/* Инициализируем выделенную память нулями */&lt;br /&gt;
		memset(dest, 0, sizeof(**Dest) * SrcLen + sizeof(**Dest));&lt;br /&gt;
		/* Основной цикл прохода по исходной строке */&lt;br /&gt;
		for (; src &amp;lt; end; src++, dest++) {&lt;br /&gt;
			/* Если значение первого байта меньше 0x80 (128) */&lt;br /&gt;
			if ((*src) &amp;lt; 0x80UL) {&lt;br /&gt;
				// Значение меньше 128&lt;br /&gt;
				(*dest) = (*src);&lt;br /&gt;
			}&lt;br /&gt;
			else if (((*src) &amp;amp; 0b11000000U) == 0b11000000U) {&lt;br /&gt;
				/* Значение больше либо равно 192 */&lt;br /&gt;
				// сохраняем первый байт(заголовок)&lt;br /&gt;
				head = *src;&lt;br /&gt;
				// Сбрасываем счётчик сдвига&lt;br /&gt;
				fshift = 0;&lt;br /&gt;
				// Сбрасываем маску-итератор&lt;br /&gt;
				iter = 0b01000000U;&lt;br /&gt;
				// Сбрасываем маску значащих битов первого байта&lt;br /&gt;
				fdata = 0b00111111U;&lt;br /&gt;
				while (iter &amp;amp; head) {&lt;br /&gt;
					// Сдвигаем указатель на последовательность на следующий байт&lt;br /&gt;
					++src;&lt;br /&gt;
					/* Проверяем битовый маркер */&lt;br /&gt;
					if (((*src) ^ 0b01000000U) &amp;gt;= 0b11000000U) {&lt;br /&gt;
						// Сдвигаем биты влево на 6(количество значащих битов)&lt;br /&gt;
						(*dest) &amp;lt;&amp;lt;= 6;&lt;br /&gt;
						// Копируем младшие биты&lt;br /&gt;
						(*dest) |= ((*src) &amp;amp; 0b00111111U);&lt;br /&gt;
						// Увеличиваем счетчик сдвига&lt;br /&gt;
						fshift += 6;&lt;br /&gt;
						// Сдвигаем маску значащих битов первого байта вправо на 1 бит&lt;br /&gt;
						fdata &amp;gt;&amp;gt;= 1;&lt;br /&gt;
						// Сдвигаем маску-итератор вправо на 1 бит&lt;br /&gt;
						iter &amp;gt;&amp;gt;= 1;&lt;br /&gt;
					}&lt;br /&gt;
					else {&lt;br /&gt;
						/* Обрабатываем ошибку кодирования.&lt;br /&gt;
							Маркером ошибки служит обнуленный указатель на декодируемую точку */&lt;br /&gt;
						sprintf(buf, &amp;quot;Ошибка кодирования. Ожидалось: &amp;#039;0b10xxxxxx&amp;#039;. Индекс: %llu\n&amp;quot;, dest - *Dest);&lt;br /&gt;
						perror(buf);&lt;br /&gt;
						// обнуляем указатель на декодируемую точку&lt;br /&gt;
						dest = NULL;&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				/* Проверяем указатель на кодируемую точку */&lt;br /&gt;
				if (dest)&lt;br /&gt;
					// Копируем значащие биты первого байта сдвинув влево подсчитаное количество раз&lt;br /&gt;
					*dest |= ((uchar_t)(head &amp;amp; fdata) &amp;lt;&amp;lt; fshift);&lt;br /&gt;
				else {&lt;br /&gt;
					// если Указатель обнулен - выходим из основного цикла&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			else {&lt;br /&gt;
				// Обрабатываем ошибку кодирования первого байта&lt;br /&gt;
				sprintf(buf, &amp;quot;Ошибка кодирования. Ожидалось: &amp;#039;0b11xxxxxx&amp;#039; получено &amp;#039;0b10xxxxxx&amp;#039; Индекс: %llu\n&amp;quot;, dest - *Dest);&lt;br /&gt;
				perror(buf);&lt;br /&gt;
				dest = NULL;&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// Проверяем на ошибки&lt;br /&gt;
		if (NULL != dest) {&lt;br /&gt;
			// На всякий случай обнуляем последний символ целевой строки&lt;br /&gt;
			*dest = (uchar_t)0U;&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			// Высвобождаем память&lt;br /&gt;
			free(*Dest);&lt;br /&gt;
			// Обнуляем целевой указатель для безопасности&lt;br /&gt;
			*Dest = NULL;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	// Ели возникла ошибка то вернётся 0, т.к. оба указателя будут равны NULL&lt;br /&gt;
	return dest - *Dest;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Маркер UTF-8 ==&lt;br /&gt;
Для указания, что файл или поток содержит символы [[Юникод]]а, в начале файла или потока может быть вставлен [[маркер последовательности байтов]] ({{lang-en|Byte order mark, BOM}}), который в случае кодирования в UTF-8 принимает форму трёх октетов: &amp;lt;code&amp;gt;EF BB BF&amp;lt;sub&amp;gt;16&amp;lt;/sub&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! !! 1-й байт !! 2-й байт !! 3-й байт&lt;br /&gt;
|-&lt;br /&gt;
| [[Бинарный код|Двоичный код]] || &amp;lt;code&amp;gt;1110 1111&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1011 1011&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1011 1111&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[Шестнадцатеричная система счисления|Шестнадцатеричный код]]&lt;br /&gt;
|&amp;lt;code&amp;gt;EF&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;BB&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;BF&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Пятый и шестой октеты ==&lt;br /&gt;
Изначально кодировка UTF-8 допускала использование до шести октетов для кодирования одного символа, однако в ноябре 2003 года стандарт RFC 3629 запретил использование пятого и шестого октетов, а диапазон кодируемых символов был ограничен символом &amp;lt;code&amp;gt;U+10FFFF&amp;lt;/code&amp;gt;. Это было сделано для обеспечения совместимости с UTF-16.&lt;br /&gt;
&lt;br /&gt;
== Возможные ошибки декодирования ==&lt;br /&gt;
Не всякая последовательность октетов является допустимой. Декодер UTF-8 должен понимать и адекватно обрабатывать такие ошибки:&lt;br /&gt;
* Недопустимый октет.&lt;br /&gt;
* октет продолжения (10xxxxxx) без начального октета.&lt;br /&gt;
* Отсутствие нужного количества октетов продолжения 10xxxxxx — например, двух после 1110xxxx.&lt;br /&gt;
* Строка обрывается посреди символа.&lt;br /&gt;
* Неэкономное кодирование — например, кодирование символа тремя октетами, когда можно двумя (существует нестандартный вариант UTF-8, который кодирует символ с кодом 0 как 1100.0000 1000.0000, отличая его от символа [[Нуль-терминированная строка|конца строки]] 0000.0000.)&lt;br /&gt;
* Последовательность октетов, декодирующаяся в недопустимую кодовую позицию (например символы суррогатных пар [[UTF-16]]).&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
{{примечания}}&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [https://utf-8.su UTF-8 Стандарт кодирования]&lt;br /&gt;
* [https://symbl.cc/ru/ UTF-8 encoding table and Unicode characters]&lt;br /&gt;
* [https://habrahabr.ru/post/138173/ UTF-8: Кодирование и декодирование]&lt;br /&gt;
* [https://www.unicode.org/faq/utf_bom.html#UTF8 UTF-8, UTF-16, UTF-32 &amp;amp; BOM — Вопросы и ответы]&lt;br /&gt;
* [https://www.unicode.org/reports/tr26/ Compatibility Encoding Scheme for UTF-16: 8-Bit (CESU-8)]&lt;br /&gt;
* [http://www.unicode.org/ Полное описание стандарта Unicode]&lt;br /&gt;
* [https://utf8everywhere.org/ UTF-8 Everywhere Manifesto]&lt;br /&gt;
* [https://www.ietf.org/rfc/rfc3629.txt RFC-3629 «UTF-8, a transformation format of ISO 10646»]&lt;br /&gt;
&lt;br /&gt;
{{Кодировки символов}}&lt;br /&gt;
{{Форматы данных}}&lt;br /&gt;
&lt;br /&gt;
[[Категория:Юникод]]&lt;br /&gt;
[[Категория:Компьютерные кодировки]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Felex67</name></author>
	</entry>
</feed>