Еще один вопрос о типах данных C

Ну, я полностью понимаю самые основные типы данных C, такие как short, int, long, float, если быть точным, все числовые типы. Эти типы необходимы, чтобы знать, что они выполняют правильные операции с правильными числами. Например, чтобы использовать FPU для добавления двух чисел с плавающей запятой. Поэтому компилятор должен знать, что это за тип.

Но когда дело доходит до персонажей, я немного не в себе. Я знаю, что базовый тип данных C предназначен для кодирования символов ASCII. Но чего я не знаю, так это зачем вообще нужен другой тип данных для символов. Почему бы вам просто не использовать 1-байтовое целочисленное значение для хранения символа ASCII. Если вы вызываете printf, вы указываете тип данных в вызове, поэтому вы можете сказать printf, что целое число представляет символ ASCII. Я не знаю, как cout разрешает тип данных, но я думаю, вы могли бы просто указать это как-то.

Другое дело, если вы хотите использовать Unicode, вы должны использовать тип данных wchar. Но что, если я хочу использовать какую-то другую, например, ISO или Windows кодировку вместо UTF? Потому что wchar кодирует символы как UTF-16 или UTF-32 (я читал, что это специфично для компилятора). И что, если я захочу использовать, например, какое-то воображаемое новое 8-байтовое кодирование текста? Какой тип данных я должен использовать для этого? Я на самом деле очень смущен этим, потому что я всегда ожидал, что если я хочу использовать UTF-32 вместо ASCII, я просто говорю компилятору: «получить значение UTF-32 символа, который я набрал, и сохранить его в поле из 4 символов». Я думал, что с текстовым кодированием нужно разобраться в конце, например, с функцией печати. Что мне просто нужно указать кодировку для использования компилятором, поскольку Windows не использует ASCII в приложениях win32, я думаю, компилятор C должен преобразовать введенный мной символ в ASCII из любого типа, который Windows отправляет в редактор C.

И последнее, что, если я хочу использовать, например, 25-байтовое целое число для некоторых сложных математических операций? C не имеет типа данных «укажи сам». Да, я знаю, что это будет сложно, так как нужно будет изменить все математические операции, потому что ЦП не может сложить 25-байтовые числа вместе. Но есть ли способ сделать это? Или есть какая-то математическая библиотека для этого? Что если я хочу вычислить число Пи до 1000000000000000 цифр? :)

Я знаю, что мой вопрос довольно длинный, но я просто хотел объяснить свои мысли как можно лучше на английском, так как это не мой родной язык, это сложно. И я считаю, что есть простой ответ на мой вопрос (вопросы), что-то, что я пропустил, что объясняет все. Я много читал о текстовом кодировании, учебниках по C, но ничего о нем. Спасибо за ваше время.


person B.Gen.Jack.O.Neill    schedule 15.04.2010    source источник
comment
Чтобы получить наилучшие ответы, в будущем вам следует использовать несколько вопросов, а не объединять их все в один.   -  person caf    schedule 16.04.2010
comment
Спасибо, подумал я, я не буду слишком засорять этот форум, если свяжу похожие вопросы вместе.   -  person B.Gen.Jack.O.Neill    schedule 17.04.2010


Ответы (4)


Ваш вопрос очень широкий, я попытаюсь решить некоторые конкретные вопросы, которые вы подняли, надеюсь, это поможет вам разобраться.

  • Тип char можно рассматривать как еще один числовой тип, как int, short и long. Совершенно нормально писать char a=3;. Разница в том, что с chars компилятор дает вам дополнительную ценность. вместо просто чисел вы также можете назначить символы ASCII переменной, такой как char a='U';, и тогда переменная получит значение ASCII этого символа, и вы также можете инициализировать массивы символов, используя буквенные строки, например: char *s="hello";.
    Это не так. измените тот факт, что в конце концов char по-прежнему является числовым типом, а строка - это просто массив чисел. Если вы посмотрите на память строки, вы увидите ASCII-коды строки.

  • Выбор char в качестве 1 байта является произвольным и в основном сохраняется таким в C по историческим причинам. более современные языки, такие как C# и Java, определяют char как 2 байта.

  • Вам не нужен «другой» тип для символов. char — это просто числовой тип, который содержит один подписанный/беззнаковый байт, так же, как short — это числовой тип, который содержит 16-битное слово со знаком. Тот факт, что этот тип данных используется для символов и строк, является просто синтаксическим сахаром, предоставляемым компилятором. 1-байтовые целые числа == char.

  • printf() работает только с символами, так как C был разработан именно так. Если бы он был разработан сегодня, возможно, он работал бы с шортами. Действительно, в Windows у вас есть версия printf(), которая работает с шортами, она называется wprintf().

  • тип wchar_t в Windows — это просто другое имя для short. где-то в файлах заголовков Windows есть такое деклерирование: typedef short wchar_t;, что и делает это. Вы можете использовать их взаимозаменяемо. Преимущество использования слова wchar_t заключается в том, что любой, кто читает ваш код, знает, что теперь вы хотите использовать символы, а не числа. Другая причина заключается в том, что если есть отдаленный шанс, что когда-нибудь Microsoft решит, что теперь они хотят использовать UTF32, то все, что им нужно сделать, это переопределить указанный выше typedef, чтобы он был typedef int wchar_t;, и все (на самом деле добиться этого будет немного сложнее). так что это изменение маловероятно в обозримом будущем)

  • Если вы хотите использовать какую-либо 8-битную кодировку, отличную от ASCII, например кодировку для иврита, которая называется «Windows-1255», вы просто используете символы. Таких кодировок много, но в наши дни использование UNICODE всегда предпочтительнее. На самом деле существует версия самого Unicode, которая подходит для 8-битных строк, то есть UTF-8. Если вы имеете дело со строками UTF-8, вам следует работать с типом данных char. Нет ничего, что ограничивало бы его работу с ASCII, так как это просто число, оно может означать что угодно.

  • Работа с такими длинными числами обычно выполняется с использованием так называемых «десятичных типов». В C этого нет, а в C# есть. Основная идея этих типов заключается в том, что они обрабатывают число, похожее на строку. Каждая цифра десятичного представления сохраняется с использованием 4 бит, поэтому 8-битная переменная может сохранять числа в диапазоне 0-99, 3-байтовый массив может сохранять значения в диапазоне 0-999999 и так далее. Таким образом, вы можете сохранять числа в любом диапазоне.
    Недостатком этого является то, что вычисления с ними выполняются намного медленнее, чем вычисления с обычными двоичными числами.
    Я не уверен, что существуют библиотеки, которые выполняют такие операции. вещь в C. Используйте Google, чтобы узнать.

person shoosh    schedule 15.04.2010
comment
char может быть как подписанным, так и беззнаковым — на усмотрение компилятора; а short всегда подписано (не без знака, как вы говорите). - person caf; 16.04.2010

На самом деле существует множество языков, в которых типы переменных не известны во время компиляции. Это, как правило, добавляет некоторые накладные расходы во время выполнения.

Чтобы ответить на ваш первый вопрос, я думаю, вы зациклились на имени «char». Тип char является однобайтовым целым числом в C (на самом деле это не совсем так — это целочисленный тип, достаточно большой, чтобы содержать любой символ из базового набора символов, но его размер зависит от реализации). Обратите внимание, что вы могут иметь как подписанные символы, так и неподписанные символы, что не имеет большого смысла, если вы говорите о типе данных, который содержит только символы. Но однобайтовое целое число в C называется «char», потому что это наиболее распространенное его использование (опять же см. заявление об отказе от ответственности выше).

Остальная часть вашего вопроса охватывает много вопросов — возможно, было бы лучше разбить его на несколько вопросов. Как и тип char, размер wchar_t зависит от реализации — единственное требование — он должен быть достаточно большим, чтобы вместить любой широкий символ. Важно понимать, что Unicode и кодировки символов в целом фактически не зависят от языка C. Также важно понимать, что наборы символов — это не то же самое, что кодировки символов.

Вот статья (по-моему, одного из основателей SO), которая дает краткое введение в наборы символов и кодировки: http://www.joelonsoftware.com/articles/Unicode.html. Как только вы лучше поймете, как они работают, вы сможете лучше сформулировать для себя некоторые вопросы. Обратите внимание, что многие наборы символов (например, кодовая страница Windows) требуют только одного байта памяти.

person Tagore Smith    schedule 15.04.2010
comment
На самом деле стандарт C определяет char и байт таким образом, что char всегда является одним байтом. - person SamB; 20.04.2010
comment
Это верно, но стандарт также определяет размер байта как достаточно большой, чтобы вместить любой символ из базового набора символов. Определение, используемое стандартом C, немного отличается от того, что обычно подразумевается под словом байт. Но, возможно, мне следовало быть более точным и сказать, что C char не обязательно является октетом. - person Tagore Smith; 21.04.2010

В C char является целым числом размером 1 байт, которое также используется для хранения символа. Символ — это просто 1-байтовое целое число в C.

И что, если я захочу использовать, например, какое-то воображаемое новое 8-байтовое кодирование текста?

Вам придется создать его самостоятельно, основываясь на типах, доступных через ваш компилятор/аппаратное обеспечение. Один из подходов может состоять в том, чтобы определить структуру с массивом из 8 символов и построить функцию для манипулирования указанной структурой со всеми операциями, которые вы хотите для этого,

потому что я всегда ожидал, что если я хочу использовать UTF-32 вместо ASCII, я просто говорю компилятору: «получить значение UTF-32 для введенного мною символа и сохранить его в поле из 4 символов.

Вы ограничены типами вашего компилятора C, на который сильно влияет аппаратное обеспечение (и стандарт C + немного истории). C — язык низкого уровня, и в нем не так уж много магии. Тем не менее, существуют библиотечные функции, которые могут позволить вам переводить между (некоторыми) наборами символов, например. функция mbtowc() и аналогичная, которая делает именно это, вы говорите ей: «Вот 16 байтов символов ISO8859-1, переведите их в UTF-16 в этот буфер, пожалуйста».

И последнее, что, если я хочу использовать, например, 25-байтовое целое число для некоторых сложных математических операций? C не имеет типа данных «укажи сам».

C позволяет вам определять свои собственные типы данных, структуры. Вы можете построить абстракцию поверх них. Люди создали такие библиотеки, см., например. здесь . Другие языки могут позволить вам еще более естественно моделировать такие типы, такие как C++, которые также позволяют вам перегружать операторы, такие как +,-,* и т. д., для работы с вашими собственными типами данных.

person nos    schedule 15.04.2010

Не существует (не было) типа «1-байтовое целое число», отличного от char (и его вариантов signed и unsigned). И хотя Windows NT (т. е. не 9x или ME) использует Unicode внутри, ваша программа будет использовать Unicode только в том случае, если вы напишете ее таким образом — вы должны либо использовать WCHAR и все W-версии вызовов win32, либо использовать TCHAR и #define UNICODE.

person SamB    schedule 15.04.2010