Для чего нужен char

Русские Блоги

Глубокое понимание char *, char **, char a [], char * a []

1. Природа массива

2. Указатель

Указатель также является переменной, Но его блок памяти хранит адрес, который идентифицирует другие местоположения. Поскольку адрес также является целым числом, на 32-битной платформе указатель по умолчанию равен 32 битам.

3. Указатель указателя

Независимо от указанного типа данных переменная-указатель всегда является целым числом из-за адреса, который она содержит.

4. Массив символов

Буквально означает массив, а элементы в массиве являются символами. Действительно, в этом его основное значение.

Его можно инициализировать, когда переменная определена на языке Си.

Когда компилятор встречает это предложение, он заполняет hello \ 0 один за другим из первого элемента в массиве str.

Поскольку в языке C нет реального типа строки, массив символов можно использовать для представления строки, поскольку адреса ее элементов являются непрерывными, что достаточно.

Язык C предусматривает, что массив представляет первый адрес ячейки памяти, где расположен массив, а также является адресом str [0], то есть str = & str [0];

К тому же

Зачем использовать первый адрес для вывода строки.

Поскольку есть еще один ключ, сущность строковой константы в языке Си на самом деле является адресом, который является проблемой, которую многим начинающим труднее понять.

Например:

Почему строка может быть назначена переменной указателя.

Разве это не противоречивый тип?

Это ключ, упомянутый выше.

На языке Си компилятор будет назначать адреса строковым константам. Если «Китай», он будет храниться в памяти как 0x3000 0x3001 0x3002 0x3003 0x3004 0x3005.

s = «Китай», что такое сознание, да, адрес.

Фактически, реальное значение s = «Китай» = 0x3000;

Это письмо кажется более интуитивным.

Разберись с этой проблемой.

Затем% s, его принцип на самом деле заключается в выводе строки через первый адрес строки, printf («% s», s); фактически ему передается адрес строки, сохраненной s.

Такие как

Вы можете увидеть s = 0x00422020, который также является первым адресом «привет»

Следовательно, printf («% s», 0x00422020); также эквивалентен.

Массив символов:

Как упоминалось ранее, str = & str [0] также равно первому адресу «hello».

Так что printf («% s», str); по сути, это printf («% s», адрес);

Операция строки в языке Си осуществляется через первый адрес ее запоминающего устройства в памяти, что является основной сущностью строки.

4.char * и char a []

Как упоминалось ранее, a представляет первый адрес строки, а указатель s также хранит адрес строки (фактически первый адрес), то есть адрес первого символа.Данные в этой единице адреса являются символом.

Это также согласуется с символом, на который указывает s.

Следовательно, s = a;

На языке C имя массива можно скопировать в указатель для представления адреса, но его нельзя присвоить имени массива. Это постоянный тип, поэтому его нельзя изменить.

Конечно, это также может быть так:

Символьный указатель может использовать косвенный оператор *, чтобы получить его содержимое, или использовать форму индекса массива [], и имя массива также можно использовать с *, поскольку он представляет адрес.

Такие как

5. Существенная разница между char * и char a []:

При определении char * s это переменная указателя, которая занимает всего четыре байта, 32 бита и используется для хранения адреса.

Конечно, это 4. Компилятор выделяет 4 байта 32-битного пространства, и адрес будет сохранен в этом пространстве.

Это представляет адрес, хранящийся в единицах s.

Это представляет адрес блока памяти, где находится сама переменная, не путайте его.

Причиной, по которой char * может добиться эффекта char a [], является характер строки, адрес. То есть, если вы дадите вам строковый адрес, вы можете использовать его по своему усмотрению, но основные свойства char * и char a [] различны.

6.char ** и char * a []

Из этого предложения вы можете видеть, что элементы в массиве являются строками, так что же такое sizeof (a)? Некоторые люди думают, что общее количество байтов в памяти составляет 5 слов 6 + 7 + 8 + 7 = 28;

Но на самом деле sizeof (a) = 16;

Взгляните на пример:

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

Обратите внимание, что эти четыре адреса не являются последовательными: они являются адресами пространства памяти, выделенного компилятором для «Китай», «Французский», «Америка» и «Немецкий», поэтому четыре адреса не связаны между собой.

Вы можете видеть 0012FF38 0012FF3C 0012FF40 0012FF44, эти четыре являются адресами, где расположена единица элемента, каждый адрес отличается на четыре байта, потому что каждый элемент является переменной-указателем, занимающей четыре байта.

Char ** является вторичным указателем, а s хранит адрес первичного указателя char *. Вторичный указатель не будет здесь подробно обсуждаться. Просто поговорим о подверженных ошибкам точках вторичного указателя.

Например:

Почему мы можем присвоить a s, потому что имя массива a представляет первый адрес блока памяти элемента массива, то есть a = & a [0] = 0012FF38;

Таким образом, данные в могут быть обработаны с

Но следует отметить, что a = s не может быть использовано. Как упоминалось ранее, a является константой.

Посмотрите на другую подверженную ошибкам точку:

Потому что тип s это char **, а тип «hello world» это char *

Хотя все они являются адресами, они указывают на разные типы, поэтому их нельзя использовать таким образом.

Что если так:

Это кажется разумным и нет проблем с компиляцией, но printf («% s», * s) завершится сбоем.
Давайте изучим это медленно.

Когда printf («% s», * s) ;, сначала вы должны сохранить адрес, сохраненный s, а затем найти адрес char * в этом адресе, который является * s;

Адрес 0x003001 «hello world» сохраняется в блоке памяти, где расположен 0x1000, * s = 0x003001;

Сначала будет найдено 0x1000, а затем 0x003001;

В переменной s хранится недопустимый случайный недоступный адрес. Никто не знает, куда он указывает, и операция * s завершится сбоем.

Поэтому, когда используется символ **, адрес памяти должен быть ему выделен.

Таким образом, s назначается используемый адрес, такой как s = 0x412f;
Затем сохраните значение «hello world» в ячейке памяти, где находится 0x412f.

Другой пример:

Наконец, размер sizoof (указателя) зависит от операционной системы компьютера.Как правило, объем памяти, занимаемый 32-разрядной операционной системой, равен 4, а размер 64-разрядного указателя операционной системы равен 8.

Printf («% s», * s) в моей Ubuntu, без сбоев.

Источник

Очень странные вещи c Java Characters

Тайна ошибки комментария и другие истории.

Для чего нужен char. Смотреть фото Для чего нужен char. Смотреть картинку Для чего нужен char. Картинка про Для чего нужен char. Фото Для чего нужен char

Вступление

Знаете ли вы, что следующее является допустимым выражением Java?

Вы можете попробовать скопировать и вставить его в основной метод любого класса и скомпилировать. Если вы затем добавите следующий оператор

и после компиляции запустите этот класс, код напечатает число 8!

А знаете ли вы, что этот комментарий вместо этого вызывает синтаксическую ошибку во время компиляции?

Тем не менее, комментарии не должны приводить к синтаксическим ошибкам. Фактически, программисты часто комментируют фрагменты кода, чтобы компилятор их игнорировал. так что же происходит?

Примитивный тип данных char

Как всем известно, char это один из восьми примитивных типов Java. Это позволяет нам хранить по одному символу. Ниже приведен простой пример, в котором значение символа присваивается типу char :

На самом деле этот тип данных используется нечасто, потому что в большинстве случаев программистам нужны последовательности символов и поэтому они предпочитают строки. Каждое буквальное значение символа должно быть заключено между двумя одинарными кавычками, чтобы не путать с двойными кавычками, используемыми для строковых литералов. Объявление строки:

используя один печатный символ на клавиатуре (например ‘&’ ).

используя специальный escape-символ (например, ‘\n’ который указывает символ перевода строки).

Давайте добавим некоторые детали в следующих трех разделах.

Печатаемые символы клавиатуры

Мы можем назначить любой символ, найденный на нашей клавиатуре, char переменной, при условии, что наши системные настройки поддерживают требуемый символ и что этот символ доступен для печати (например, клавиши «Canc» и «Enter» не печатаются).

Тип данных char хранится в 2 байтах (16 бит), а диапазон состоит только из положительных чисел от 0 до 65 535. Фактически, существует «отображение», которое связывает определенный символ с каждым числом. Это отображение (или кодирование) определяется стандартом Unicode (более подробно описанным в следующем разделе).

Формат Unicode (шестнадцатеричное представление)

Мы можем напрямую присвоить Unicode char значение в шестнадцатеричном формате, используя 4 цифры, которые однозначно идентифицируют данный символ, добавляя к нему префикс \u (всегда в нижнем регистре). Например:

В данном случае мы говорим о литерале в формате Unicode (или литерале в шестнадцатеричном формате). Фактически, при использовании 4 цифр в шестнадцатеричном формате охватывается ровно 65 536 символов.

Специальные escape-символы

В char типе также можно хранить специальные escape-символы, то есть последовательности символов, которые вызывают определенное поведение при печати:

\b эквивалентно backspace, отмене слева (эквивалентно клавише Delete).

\n эквивалентно переводу строки (эквивалентно клавише Ente).

\\ равняется только одному \ (только потому, что символ \ используется для escape-символов).

\t эквивалентно горизонтальной табуляции (эквивалентно клавише TAB).

\’ эквивалентно одинарной кавычке (одинарная кавычка ограничивает литерал символа).

\» эквивалентно двойной кавычке (двойная кавычка ограничивает литерал строки).

\r представляет собой возврат каретки (специальный символ, который перемещает курсор в начало строки).

\f представляет собой подачу страницы (неиспользуемый специальный символ, представляющий курсор, перемещающийся на следующую страницу документа).

Обратите внимание, что присвоение литерала ‘»‘ символу совершенно законно, поэтому следующий оператор:

что эквивалентно следующему коду:

правильно и напечатает символ двойной кавычки:

Если бы мы попытались не использовать escape-символ для одиночных кавычек, например, со следующим утверждением:

мы получим следующие ошибки времени компиляции, поскольку компилятор не сможет различить разделители символов:

Поскольку разделители строковых литералов представлены в двойных кавычках, ситуация обратная. Фактически, внутри строки можно заключить одинарные кавычки:

С другой стороны, мы должны использовать \» escape-символ, чтобы использовать двойные кавычки в строке. Итак, следующее утверждение:

вызовет следующие ошибки компиляции:

Вместо этого верна следующая инструкция:

Написание Java кода в формате Unicode

Литеральный формат Unicode также можно использовать для замены любой строки нашего кода. Фактически, компилятор сначала преобразует формат Unicode в символ, а затем оценивает синтаксис. Например, мы могли бы переписать следующий оператор:

Фактически, если мы добавим к предыдущей строке следующий оператор:

Несомненно, это бесполезный способ написания нашего кода. Но может быть полезно знать эту функцию, поскольку она позволяет нам понять некоторые ошибки, которые (редко) случаются.

Формат Unicode для escape-символов

мы получим следующую ошибку времени компиляции:

В реальности, компилятор преобразует предыдущий код в следующий перед его оценкой:

Формат Unicode был преобразован в символ новой строки, и предыдущий синтаксис не является допустимым синтаксисом для компилятора Java.

Также в этом случае компилятор преобразует предыдущий код следующим образом:

что приведет к следующим ошибкам времени компиляции:

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

мы получим следующую ошибку времени компиляции:

Фактически, компилятор преобразовал число в формате Unicode в возврат каретки, вернув курсор в начало строки, и то, что должно было быть второй одинарной кавычкой, стало первой.

мы получим следующую ошибку времени компиляции:

Это потому, что предыдущий код будет преобразован в следующий:

и поэтому пара символов ‘ рассматривается как escape-символ, соответствующий одинарной кавычке, и поэтому в буквальном закрытии отсутствует другая одинарная кавычка.

проблем не будет. Но если мы используем этот символ внутри строки:

мы получим следующую ошибку времени компиляции:

поскольку предыдущий код будет преобразован в следующий:

Тайна ошибки комментария

Еще более странная ситуация возникает при использовании однострочных комментариев для форматов Unicode, таких как возврат каретки или перевод строки. Например, несмотря на то, что оба следующих оператора закомментированы, могут возникнуть ошибки во время компиляции!

Это связано с тем, что компилятор всегда преобразует шестнадцатеричные форматы с помощью символов перевода строки и возврата каретки, которые несовместимы с однострочными комментариями; они печатают символы вне комментария!

Чтобы разрешить ситуацию, используйте обозначение многострочного комментария, например:

Выводы

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

Примечание автора: эта статья представляет собой короткий отрывок из раздела 3.3.5 «Примитивные символьные типы данных» тома 1 моей книги «Java для пришельцев». Для получения дополнительной информации посетите сайт книги (вы можете загрузить раздел 3.3.5 из области «Примеры»).

Источник

4.11 – Символы

На данный момент базовые типы данных, которые мы рассмотрели, использовались для хранения чисел (целые числа и числа с плавающей запятой) или значений истина/ложь (логические значения). Но что, если мы хотим хранить буквы?

ASCII расшифровывается как American Standard Code for Information Interchange (Американский стандартный код для обмена информацией) и определяет конкретный способ представления английских символов (плюс несколько других символов) в виде чисел от 0 до 127 (называемых кодом ASCII или кодовым обозначением). Например, код ASCII 97 интерпретируется как символ ‘ а ‘.

Символьные литералы всегда помещаются в одинарные кавычки (например, ‘ g ‘, ‘ 1 ‘, ‘ ‘).

Ниже приведена полная таблица символов ASCII:

Таблица символов ASCII

CodeSymbolCodeSymbolCodeSymbolCodeSymbol
0NUL (null)32(space)64@96`
1SOH (start of header, начало «заголовка»)33!65A97a
2STX (start of text, начало «текста»)3466B98b
3ETX (end of text, конец «текста»)35#67C99c
4EOT (end of transmission, конец передачи)36$68D100d
5ENQ (enquiry, «Прошу подтверждения!»)37%69E101e
6ACK (acknowledge, «Подтверждаю!»)38&70F102f
7BEL (bell, звуковой сигнал: звонок)3971G103g
8BS (backspace, возврат на один символ)40(72H104h
9HT (horizontal tab, горизонтальная табуляция)41)73I105i
10LF (line feed/new line, перевод строки)42*74J106j
11VT (vertical tab, вертикальная табуляция)43+75K107k
12FF (form feed / new page, «прогон страницы», новая страница)44,76L108l
13CR (carriage return, возврат каретки)4577M109m
14SO (shift out, «Переключиться на другую ленту (кодировку)»)46.78N110n
15SI (shift in, «Переключиться на исходную ленту (кодировку)»)47/79O111o
16DLE (data link escape, «Экранирование канала данных»)48080P112p
17DC1 (data control 1, первый символ управления устройством)49181Q113q
18DC2 (data control 2, второй символ управления устройством)50282R114r
19DC3 (data control 3, третий символ управления устройством)51383S115s
20DC4 (data control 4, четвертый символ управления устройством)52484T116t
21NAK (negative acknowledge, «Не подтверждаю!»)53585U117u
22SYN (synchronous idle)54686V118v
23ETB (end of transmission block, конец текстового блока)55787W119w
24CAN (cancel, «Отмена»)56888X120x
25EM (end of medium, «Конец носителя»)57989Y121y
26SUB (substitute, «Подставить»)58:90Z122z
27ESC (escape)59;91[123 <
28FS (file separator, разделитель файлов)6094^126
31US (unit separator, разделитель юнитов)63?95_127DEL (delete, стереть последний символ)

Коды 0–31 называются непечатаемыми символами и в основном используются для форматирования и управления принтерами. Большинство из них сейчас устарели.

Коды 32–127 называются печатными символами и представляют собой буквы, цифры и знаки препинания, которые большинство компьютеров используют для отображения основного английского текста.

Инициализация переменных char

Вы также можете инициализировать переменные типа char целыми числами, но этого, если возможно, следует избегать.

Предупреждение

Будьте осторожны, чтобы не перепутать символы чисел с целыми числами. Следующие две инициализации не эквивалентны:

Символы чисел предназначены для использования, когда мы хотим представить числа в виде текста, а не в виде чисел и применения к ним математических операций.

Печать переменных типа char

Данная программа дает следующий результат:

Мы также можем напрямую выводить символьные литералы:

В результате это дает:

Напоминание

Печать переменных char как целых чисел через приведение типов

Однако это довольно коряво. Лучше использовать приведение типа. Приведение типа создает значение одного типа из значения другого типа. Для преобразования между базовыми типами данных (например, из char в int или наоборот) мы используем приведение типа, называемое статическим приведением.

Синтаксис статического приведения выглядит немного забавным:

Ключевые выводы

Всякий раз, когда вы видите синтаксис C++ (за исключением препроцессора), в котором используются угловые скобки, то, что между угловыми скобками, скорее всего, будет типом. Обычно C++ работает с концепциями, которым нужен параметризуемый тип.

Ниже показан пример использования статического приведения для создания целочисленного значения из нашего значения char :

Эта программа дает следующий вывод:

Важно отметить, что параметр static_cast вычисляется как выражение. Когда мы передаем переменную, эта переменная вычисляется для получения ее значения, которое затем преобразуется в новый тип. На переменную не влияет приведение ее значения к новому типу. В приведенном выше случае переменная ch по-прежнему является char и сохраняет то же значение.

О статическом приведении типов и других типах приведения мы поговорим подробнее в следующем уроке (8.5 – Явное преобразование типов (приведение) и static_cast ).

Ввод символов

Следующая программа просит пользователя ввести символ, а затем печатает его как символ и его код ASCII:

Ниже показан результат одного запуска:

Вы можете увидеть это поведение в следующем примере:

Размер, диапазон и символ по умолчанию у переменных char

char определяется C++ всегда размером 1 байт. По умолчанию char может быть со знаком или без знака (хотя обычно он со знаком). Если вы используете переменные char для хранения символов ASCII, вам не нужно указывать знак (поскольку переменные char со знаком и без знака могут содержать значения от 0 до 127).

Экранированные последовательности

В C++ есть некоторые символы, которые имеют особое значение. Эти символы называются экранированными последовательностями (управляющими последовательностями, escape-последовательностями). Экранированная последовательность начинается с символа ‘\’ (обратный слеш), за которым следует буква или цифра.

Вы уже видели наиболее распространенную экранированную последовательность: ‘ \n ‘, которую можно использовать для вставки символа новой строки в текстовую строку:

Эта программа выдает:

Еще одна часто используемая экранированная последовательность – ‘ \t ‘, которая включает горизонтальную табуляцию:

Три других примечательных экранированных последовательности:

Ниже приведена таблица всех экранированных последовательностей:

Экранированные последовательности

НазваниеСимволНазначение
Предупреждение\aВыдает предупреждение, например звуковой сигнал
Backspace\bПеремещает курсор на одну позицию назад
Перевод страницы\fПеремещает курсор на следующую логическую страницу
Новая строка\nПеремещает курсор на следующую строку
Возврат каретки\rПеремещает курсор в начало строки
Горизонтальная табуляция\tПечать горизонтальной табуляции
Вертикальная табуляция\vПечатает вертикальную табуляцию
Одинарная кавычка\’Печать одинарной кавычки
Двойная кавычкаПечать двойной кавычки
Обратная косая черта\\Печатает обратный слеш
Вопросительный знак\?Печатает вопросительный знак
Больше не актуально. Вы можете использовать вопросительные знаки без экранирования.
Восьмеричное число\(число)Преобразуется в символ, представленный восьмеричным числом
Шестнадцатеричное число\x(число)Преобразуется в символ, представленный шестнадцатеричным числом

Вот несколько примеров:

Эта программа напечатает:

Новая строка ( \n ) против std::endl

В чем разница между заключением символов в одинарные и двойные кавычки?

Отдельные символы всегда заключаются в одинарные кавычки (например, ‘a’, ‘+’, ‘5’). char может представлять только один символ (например, букву а, знак плюса, цифру 5). Что-то вроде этого некорректно:

Текст, заключенный в двойные кавычки (например, «Hello, world!»), называется строкой. Строка – это набор последовательных символов (и, таким образом, строка может содержать несколько символов).

Пока вы можете использовать строковые литералы в своем коде:

Мы обсудим строки в следующем уроке (4.12 – Знакомство с std::string ).

Правило

Всегда помещайте отдельные символы в одинарные кавычки (например, ‘ t ‘ или ‘ \n ‘, а не » t » или » \n «). Это помогает компилятору более эффективно выполнять оптимизацию.

wchar_t следует избегать почти во всех случаях (за исключением взаимодействия с Windows API). Его размер определяется реализацией и не является надежным. Он не рекомендуется для использования.

В качестве отступления.

Англоязычный термин «deprecated» (не рекомендуется) означает «всё еще поддерживается, но больше не рекомендуется для использования, потому что он был заменен чем-то лучшим или больше не считается безопасным».

Подобно тому, как ASCII сопоставляет целые числа 0–127 с символами английского алфавита, существуют и другие стандарты кодировки символов для сопоставления целых чисел (разного размера) с символами других языков. Наиболее известной кодировкой за пределами диапазона ASCII является стандарт Unicode (Юникод), который сопоставляет более 110 000 целых чисел с символами на многих языках. Поскольку Unicode содержит очень много кодовых обозначений, то для одного кодового обозначения, чтобы представить один символ, Unicode требуется 32 бита (кодировка UTF-32). Однако символы Unicode также могут быть закодированы с использованием 16-ти или 8-ми битов (кодировки UTF-16 и UTF-8 соответственно).

char16_t и char32_t были добавлены в C++11 для обеспечения явной поддержки 16-битных и 32-битных символов Unicode. char8_t был добавлен в C++20.

А пока при работе с символами (и строками) вы должны использовать только символы ASCII. Использование символов из других наборов символов может привести к неправильному отображению ваших символов.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *