Unicode определяет один огромный набор символов, присваивая одно уникальное целочисленное значение каждому графическому символу (это является основным упрощением, и на самом деле это не так, но это достаточно близко для целей этого вопроса). UTF-8/16/32 - это просто разные способы кодирования этого.
Вкратце, UTF-32 использует 32-битные значения для каждого символа. Это позволяет им использовать код фиксированной ширины для каждого символа.
UTF-16 использует 16-битный по умолчанию, но это дает только 65 тыс. Возможных символов, что далеко не достаточно для полного набора Unicode. Поэтому некоторые символы используют пары 16-битных значений.
И UTF-8 по умолчанию использует 8-битные значения, что означает, что 127 первых значений являются однобайтовыми символами фиксированной ширины (старший бит используется для обозначения того, что это начало многобайтовой последовательности оставляя 7 битов для фактического значения символа). Все остальные символы кодируются как последовательности длиной до 4 байтов (если память служит).
И это приводит нас к преимуществам. Любой символ ASCII напрямую совместим с UTF-8, поэтому для обновления устаревших приложений UTF-8 является распространенным и очевидным выбором. Почти во всех случаях он также будет использовать наименьшее количество памяти. С другой стороны, вы не можете дать никаких гарантий относительно ширины символа. Ширина может быть 1, 2, 3 или 4 символа, что затрудняет манипулирование строками.
UTF-32 противоположен, он использует больше всего памяти (каждый символ имеет фиксированную ширину 4 байта), но с другой стороны, вы знаете , что каждый символ имеет такую точную длину, поэтому манипулирование строк становится намного проще. Вы можете вычислить количество символов в строке просто по длине в байтах строки. Вы не можете сделать это с UTF-8.
UTF-16 - это компромисс. Это позволяет большинству символов вписываться в 16-битное значение фиксированной ширины. Поэтому, пока у вас нет китайских символов, музыкальных нот или каких-либо других, вы можете предположить, что каждый символ имеет ширину 16 бит. Он использует меньше памяти, чем UTF-32. Но это в некотором смысле «худшее из обоих миров». Он почти всегда использует больше памяти, чем UTF-8, и все же не избегает проблемы, которая преследует UTF-8 (символы переменной длины).
Наконец, часто полезно просто посмотреть, что поддерживает платформа. Windows использует UTF-16 для внутреннего использования, поэтому для Windows это очевидный выбор.
Linux немного отличается, но они обычно используют UTF-8 для всего, что соответствует Unicode.
Такой короткий ответ: все три кодировки могут кодировать один и тот же набор символов, но они представляют каждый символ как разные последовательности байтов.