Константные переменные в c

Константные переменные в c

Константа — это ограниченная последовательность символов алфавита языка, представляющая собой изображение фиксированного (неизменяемого) объекта.

Константы бывают числовые, символьные и строковые. Числовые константы делятся на целочисленные и вещественные.

Целочисленные константы

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

Десятичные Последовательность цифр ( 0 — 9 ), которая начинаются с цифры, отличной от нуля.
Пример: 1, -29, 385. Исключение — число 0.
Восьмеричные Последовательность цифр ( 0 — 7 ), которая всегда начинается с 0 .
Пример: 00, 071, -052, -03.
Шестнадцатеричные Последовательность шестнадцатеричных цифр ( 0 — 9 и A — F ), которой предшествует присутствует 0x или 0X .
Пример: 0x0, 0x1, -0x2AF, 0x17.

Двоичная система представления данных непосредственно в языке Си не поддерживается. Однако можно воспользоваться файлом binary.h, в котором определены двоичные константы в пределах байта.

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

Результат выполнения

В зависимости от значения целой константы компилятор присваивает ей тот или иной тип ( char , int , long int ).

С помощью суффикса U (или u ) можно представить целую константу в виде беззнакового целого.

Например, Константе 200U выделяется 1 байт, и старший бит используется для представления одного из разрядов кода числа и диапазон значений становится от 0 до 255 . Суффикс L (или l ) позволяет выделить целой константе 8 байт ( long int ).

Совместное использование в любом порядке суффиксов U (или u ) и L (или l ) позволяет приписать целой константе тип unsigned long int , и она займет в памяти 64 разряда, причем знаковый разряд будет использоваться для представления разряда кода (а не знака).

Вещественные константы

Константа с плавающей точкой (вещественная константа) всегда представляется числом с плавающей точкой двойной точности, т. е. как имеющая тип double , и состоит из следующих частей:

  • целой части — последовательности цифр;
  • точки — разделителя целой и дробной части;
  • дробной части — последовательности цифр;
  • символа экспоненты е или E ;
  • экспоненты в виде целой константы (может быть со знаком).

Любая часть (но не обе сразу) из нижеследующих пар может быть опущена:

  • целая или дробная часть;
  • точка или символ е ( Е ) и экспонента в виде целой константы.

Примеры вещественных констант

По умолчанию компилятор присваивает вещественному числу тип double . Если программиста не устраивает тип, который компилятор приписывает константе, то тип можно явно указать в записи константы с помощью следующих суффиксов:

  • F (или f ) — float для простых вещественных констант,
  • L (или l ) — long double для вещественных констант двойной расширенной точности.
  • 3.14159F — константа типа float , занимающая 4 байта;
  • 3.14L — константа типа long double , занимающая 10 байт.

Символьные константы

Символьная константа — это один символ, например: ‘z’ . В качестве символьных констант также могут использоваться управляющие коды, не имеющие графического представления. При этом код управляющего символа начинается с символа ‘’ (обратный слеш).

Код Обозначение Описание
0x00 ‘’ Нуль-символ, NULL
0x07 ‘a’ Звуковой сигнал.
0x08 ‘’ Возврат на 1 шаг (Backspace)
0x09 ‘ ’ Горизонтальная табуляция (Tab)
0x0A
Перевод строки (Enter)
0x0B ‘v’ Вертикальная табуляция (в консоли аналогична переводу строки)
0x0C ‘f’ Смена страницы
0x0D
Возврат каретки

Как правило, нажатие клавиши Enter генерирует сразу два управляющих символа — перевод строки ( 0x0A ) и возврат каретки ( 0x0D ).

Все символьные константы имеют тип char и занимают в памяти 1 байт. Значением символьной константы является числовое значение её внутреннего кода.

Строковые константы

Строковая константа — это последовательность символов, заключенная в кавычки, например:

«Это строковая константа»

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

Читайте также:  Контент 9190 как отключить

В конце каждой строковой константы компилятор помещает ‘’ (нуль-символ), чтобы программе было возможно определить конец строки. Такое представление означает, что размер строковой константы не ограничен каким-либо пределом, но для определения длины строковой константы её нужно полностью просмотреть.

Поскольку строковая константа состоит из символов, то она имеет тип char . Количество ячеек памяти, необходимое для хранения строковой константы на 1 больше количества символов в ней (1 байт используется для хранения нуль-символа).

Символьная константа ‘x’ и строка из одного символа «x» — не одно и то же. Символьная константа — это символ, используемый для числового представления буквы x, а строковая константа «x» содержит символ ‘x’ и нуль-символ ‘’ и занимает в памяти 2 байта. Если в программе строковые константы записаны одна за другой через разделители, то при выполнении программы они будут размещаться в последовательных ячейках памяти.

Переменные

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

Любая переменная до ее использования в программе на языке Си должна быть объявлена, то есть для нее должны быть указаны тип и имя (идентификатор).

Объявление переменных в Си осуществляется в форме

ТипПеременной ИмяПеременной;

Каждую переменную можно снабдить комментарием, поясняющим ее смысл. Например,

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

При объявлении переменной ей может быть присвоено начальное значение в форме
ТипПеременной ИмяПеременной=значение;

Введение

С помощью ключевого слова const в C++ можно объявлять не только константы. Оно имеет много значений. И не лишним будем понимать каждое из них. Это позволяет писать более надежный код, указывая компилятору на ограничения, которые он должен проверять. Таким образом, любая попытка неправильного использования переменной или функции, объявленной с использованием const , будет выявлена на самых ранних этапах.

Реклама

Переменные и const

Наиболее простой и интуитивно понятный вариант использования const заключается в объявлении константных значений:

Похожего результата можно добиться с помощью макросов:

Но вариант с макросом не столь хорош, поскольку не дает возможности указать тип переменной. Из-за возможных проблем с типизацией лучше пользоваться константами, а не макросами. Более того, макросов лучше и вовсе избегать. В C++ реализована прекрасная поддержка шаблонных функций и классов, которые в большинстве случаев представляют более надежную альтернативу. Однако стоит признать, что бывают случаи, когда макросы оказываются полезными. Но сейчас речь не о них.

Таким образом, если мы объявили переменную с const , то значение должно быть присвоено сразу. Потом уже ничего не сделать. А что, если нам надо объявить константный вектор? В C++11 для этого предусмотрена специальная конструкция:

А что, если мы по какой-то причине не может пользоваться C++11? И в этом случае можно легко объявить константный вектор:

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

Константная ссылка объявляется схожим образом:

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

Читайте также:  Как снять рут права на андроид

Для указателей существует три варианта использования const :

В варианте 1 мы получили указатель, который можно использовать как более гибкую константную ссылку. Он работает почти так же, но мы можем в любой момент сослаться на другую переменную. Вариант 2 работает так же, как обычная ссылка. Значение менять можно, а указать на другую переменную не выйдет. И наконец вариант 3. Он равносилен случаю константной ссылки. То есть один раз объявили указатель и ничего больше менять не можем.

В первом и втором варианте вполне можно обойтись использованием ссылок. Особой разницы нет. Для третьего ограничиться ссылкой получится не всегда. Например:

Строку в стиле C с помощью ссылки мы объявить не сможем. Нужен указатель. И он должен быть константным, поскольку изменение содержания строки запрещено и приведет к неопределенному поведению. А второй const здесь не помешает, чтобы получить жесткую привязку указателя к заданному значению и запретить случайные присвоения:

Реклама

Функции и const

Общее правило для применений const в функциях достаточно простое. Входные параметры лучше объявлять с ключевым словом const . Однако примитивные типы int , double , char и т.д. являются исключениями из этого правила. Это объясняется тем, что примитивные типы эффективнее передавать по значению, а не по ссылке или указателю. Причиной этому служит то, что большинство примитивных типов меньше по размеру, чем адрес в памяти, который нужно было бы передать в противном случае. Кроме того, передача по значению упрощает работу оптимизатору, поскольку выполняется прямое копирование, а не косвенные операции в адресном пространстве.

Если же вы хотите передать в функцию объект структуры или класс, то используйте константную ссылку:

Каноничным примером на этот случай является конструктор копирования:

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

Еще const можно использовать для объявления константных функций-членов классов:

У класса в примере две функции: set() и get() . Первая предназначена для установки значения, а вторая для его получения. Ключевое слово const в этом случае позволяет нам явно об этом сообщить. Причем, эта информация будет полезна и компилятору, и тем, кто будет работать с нашим классом. Ведь они будут знать, что константные функции-члены не меняют состояние класса. Можно сравнить это с флагом read-only. Вот что будет, если передать константную ссылку на объект класса MyClass в функцию:

То есть объявив функцию-член get() , как константную, мы пояснили компилятору, что она не меняет состояние объекта и предназначена только для чтения. Если бы мы забыли про const , то в функции myFunction() мы бы ничего не смогли сделать с экземплярами класса MyClass , а компилятор бы выдавал ошибки при попытке вызова его функций-членов. Но если бы оказалось, что нам и правда нужно менять состояние объекта, то ключевое слово const из сигнатуры функции пришлось бы убрать. А по принятым соглашениям ссылку имело бы смысл заменить на указатель:

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

И что же делать? — Для этого в C++ предусмотрено ключевое слово mutable . Если мы объявим поле мьютекса, как mutable , то укажем компилятору, что состояние объекта может меняться даже в константных функциях-членах:

Заключение

Вот мы и разобрались с ключевым словом const в С++. Оно имеет довольно много значений и позволяет улучшить надежность и читаемость кода, если правильно им пользоваться. Поэтому я нахожу довольно странным, что в большинстве других языков программирования, которые мне известны, хоть и есть некие аналоги const , но имеют в них ограниченную область применения. Более того, я считаю, что в C++ реализована одна из лучших возможных схем управления константами.

Читайте также:  Вместо русских букв вопросительные знаки

Обновл. 2 Янв 2020 |

В уроке №37 мы узнали, что фундаментальные типы данных (int, double, char и т.д.) можно сделать константными, используя ключевое слово const, и что все константные переменные должны быть инициализированы во время объявления. В случае с константными фундаментальными типами данных инициализация может быть копирующей, прямой или uniform:

Константные объекты классов

Объекты классов можно сделать константными (используя ключевое слово const). Инициализация выполняется через конструкторы классов:

Как только константный объект класса инициализируется через конструктор, то любая попытка изменить переменные-члены объекта запрещена, так как это нарушает принципы константности объекта. Запрещается как изменение переменных-членов напрямую (если они являются public), так и вызов методов (сеттеров), с помощью которых можно установить значения переменным-членам. Рассмотрим следующий класс:

Строчки №16-17 вызовут ошибки компиляции, так как они нарушают принципы константности объекта, пытаясь напрямую изменить переменную-член, и вызывая сеттер для изменения значения переменной-члена.

Константные методы классов

Теперь рассмотрим следующую строчку кода:

Удивительно, но это также вызовет ошибку компиляции, хотя getValue() не делает ничего для изменения переменной-члена! Оказывается, константные объекты класса могут явно вызывать только константные методы класса, а getValue() не указан как константный метод. Константный метод — это метод, который гарантирует, что не будет изменять объект или вызывать неконстантные методы класса (поскольку они могут изменить объект).

Чтобы сделать getValue() константным, нужно просто добавить ключевое слово const к прототипу функции после списка параметров, но перед телом функции:

Теперь getValue() является константным методом, что означает, что мы можем вызывать его через любой константный объект.

Для методов, определённых вне тела класса, ключевое слово const должно использоваться как в прототипе функции в теле класса, так и в определении функции:

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

В этом примере resetValue() был установлен константным, но он пытается изменить значение m_value . Это вызовет ошибку компиляции.

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

Стоит отметить, что константный объект класса может вызывать конструктор, который будет инициализировать все, некоторые или ни одну из переменных-членов!

Правило: Делайте все ваши методы, которые не изменяют данные объекта класса, константными.

Константные ссылки и классы

Ещё одним способом создания константных объектов является передача объектов в функцию по константной ссылке.

В уроке №98 мы рассмотрели преимущества передачи аргументов по константной ссылке, нежели по значению. Вкратце: передача аргументов по значению создаёт копию значения (что является медленным процессом), большую часть времени нам не нужна копия, а ссылка уже указывает на исходный аргумент и является более эффективной, так как избегает создания и использование ненужной копии. Мы обычно делаем ссылку константной для гарантии того, что функция не изменит значение аргумента и позволит функции работать с r-values (например, литералами).

Можете ли вы определить, что не так со следующим кодом?

Ссылка на основную публикацию
Клавиатура на айфоне фото
Восемь лет назад Стив Джобс анонсировал первый смартфон компании Apple. Одной из главных особенностей iPhone являлась возможность навигации по меню...
Какие комбинации клавиш необходимы для получения символов
Здравствуйте! Вы никогда не задумывались, сколько порой приходится тратить времени на обычные операции: выделить что-то мышкой, скопировать, затем вставить в...
Какие компрессоры стоят в холодильниках бирюса
С появлением широкого ассортимента импортного холодильного оборудования бытовая техника отечественного производства постепенно отошла на второй план. Однако ошибочно думать, что...
Клавиатура не отрывая пальца
Непрерывный ввод — это функция, которая позволяет вводить текст, проведя пальцем по клавиатуре. Это работает следующим образом. Допустим, вам нужно...
Adblock detector