Переменные в С++

В программировании существует понятие "Переменная". Я очень долго не мог понять, что это такое. Возможно, какой-нибудь читатель попал на эту страницу, потому что испытывает сложности в осмыслении сущности "переменная".

  • Переменная — это нечто такое, что способно изменять свое значение в ходе выполнения программы

Вспомним самое обычные арифметическое уравнение: x = a + b.

В этом уравнении присутствуют три именованных неизвестных:

  • x
  • a
  • b
Каждое неизвестное в этом уравнении может изменять своё состояние: за названием неизвестного сокрыто какое-либо значение. В каких-то неизвестных значения задаём мы, какие-то неизвестные вычисляются по формулам с помощью ставшими изветными неизвестных. Любое изменение значения равносильно изменению состояния.
В компьютере почти все то же самое.

  • Переменная в языке C++ представляет собой название неизвестного, такого неизвестного, значение-состояние которому можно задавать или изменять во время работы программы
Информация в компьютере хранится в памяти. Минимальная единица информации хранится в одной ячейке памяти. У любой ячейки памяти есть свой собственный физический адрес. У каждой ячейки памяти свой индивидуальный физический адрес.
Когда мы хотим, чтобы компьютер, например, выводил некоторое значение на монитор, нам необходимо заставить компьютер запомнить это значение.
Запоминаемое компьютером значение попадает в некоторую область памяти, где и хранится.
Область памяти представляет собой целостный блок, собранный из какого-то числа ячеек.
Хранимое внутри области памяти значение определяется компилятором с помощью первой ячейки.
У каждой ячейки есть собственный физический адрес.
В C++ обращение к адресу первой ячейки некоторого блока памяти эквивалентно обращению ко всему блоку блоку памяти.
Чтобы хранимое в блоке памяти значение, например, отображалось на экране, нужно вытащить значение из блока памяти.
Чтобы вытащить значение из блока памяти, нужен адрес первой ячейки этого блока памяти.
Обращением к адресу первой ячейки блока памяти всегда можно вытащить значение, хранимое внутри всего блока.

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

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

Если временно не обращать внимание на int, то можно заметить, что сам по себе пример кода напоминает школьный пример из алгебры. Здесь и x и y — это названия, за которыми сокрыты неизвестные данные: эти данные будут изменяться в ходе работы программы. Такие названия являются названиями блоков памяти.

  • Переменная есть блок памяти, разрешающий изменять хранимые внутри себя данные

.

Процесс работы программы, созданной с помощью листинга №2:

  • В начале работы программы в x присвоится 2, в y, соответственно, 3
  • После присваиваний значений в переменные срабатывает часть кода, изменяющая переменную x, согласно какому-то выражению (сейчас этим выражением является формула x+y)
  • Изменённое значение остаётся лежать в блоке памяти, названным x, поэтому это значение можно вытащить в любой момент времени, пока компилятор C++ уведомлен об этом блоке памяти
Так как в блоке памяти происходят изменения с данными, то такие именованные блоки памяти называют переменными (перемена значений).

Т. е. в одном блоке памяти в разные моменты времени могут лежать разные данные.

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

Компиляторам C++ нужно сообщать, каких размеров должны быть блоки выделяемой памяти. Такого вида информирование происходит путём объявления типов. Объявление типа переменной не что иное, как объяснение компилятору необходимых размеров для блока памяти.
  • Типы переменным в C++ задаются только один раз, изменять их в ходе работы программы нельзя, т. е. нельзя изменять размеры выделенных блоков памяти, можно только уничтожать один блок ради создания другого (это при работе с указателями).
В C++ типы делятся на фундаментальные (они же и базовые, и примитивные) и составные.
К фундаментальным типам относятся:

  • Символьный вид типов: char, unsigned char, signed char — относится к целочисленным типам
  • Целочисленные виды типов: short int, int, long int, long long int — относится к целочисленным типам
  • Расширенный символьный вид типов: wchar_t — относится к целочисленным типам,
  • Булев вид типов: bool — относится к целочисленным типам (3.9.1 — 7)
  • Вид типов с плавающей точкой (в народе — дробные числа): float, double, long double — относится к типам с плавающей точкой
  • Вид пустого типа: void — относится к неполным типам. (3.9.1 — 9)
  • std::nullptr_t — нулевая указательная константа (С++11)
К составным типам относятся:

  • Массивы
  • Функции
  • Указатели
  • Ссылки
  • Классы
  • Объединения
  • Перечисления
  • Указатели на нестатические члены классов (эти указатели отличаются по поведению от обычных указателей)
Для работы с числами используют целочисленные типы, эти типы могут быть знаковыми и беззнаковыми. Знаковые типы — это типы для переменных, способных принимать отрицательные значения, а беззнаковые, соответственно, отрицательных значений принимать не способны.
Поскольку числа имеют особенность быть отрицательными, то численным типам необходим знак + или . Иногда не нужны отрицательные числа, тогда имеет смысл использовать беззнаковый тип, благодаря которому возможно использовать дополнительные положительные числа.
short int — Это тип. Указывается перед переменной, хранящей целые числа.
int — Это тип. Указывается перед переменной, хранящей целые числа.
long int — Это тип. Указывается перед переменной, хранящей целые числа.
В short int и long int слово int можно опускать: short, long


Когда нужно использовать свойство знаковости чисел (только положительные, либо не только положительные, но обязательно и отрицательные), используют ключевые слова signed (знаковое) и unsigned (беззнаковое):


В работе со знаками (при выборе объявления знаковых, либо беззнаковых типов) программист выбирает диапазон. Есть два диапазона чисел, эти диапазоны чисел имеют одинаковую ёмкость: в каждый можно уместить одинаковое количество чисел (если в первый 256, то и во второй 256, если в первый 1024, то и во второй 1024).

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

Возраст человека не может быть отрицательным. Если бы тип некоторой переменной ограничивался умением воспринимать только 6 значений, то тогда знаковый тип (signed) не мог бы использовать значения 3, 4 и 5:

-5
-4
-3
-2
-1
0
1
2
3
4
5

6

-5
-4
-3
-2
-1
0
1
2

3
4
5
6

Согласитесь, что это не очень хорошо. Поэтому в некоторых изучаемых примерах вы будете встречать объявления беззнаковых типов (unsigned) либо явно знаковых (signed).

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

Все целочисленные типы могут иметь одинаковый размер. То есть блокам памяти может выделяться одно и то же число байт, независимо от того, что в один блок памяти вносится, например, char, а в другой long long int.
Из целочисленных числовых типов для работы программ в большинстве случаев хватает типа int.
Размеры целочисленных типов во всех компиляторах C++ подчиняются следующему неравенству:

  • char <= short <= int <= long <= long long
Расчитать количество вмещаемых значений в знаковый и беззнаковый тип можно по формулам:
Левый (знаковый) -2n-1 … 2n-1 — 1
Правый (беззнаковый) 0 … 2n — 1
n — количество бит. Один байт = 8 бит.
Мир не ограничивается только целыми числами, поэтому существуют типы, называемые типами с плавающей точкой. В отличие от целочисленых типов они не могут быть объявлены как беззнаковые (либо знаковые):


Размер выделяемой памяти для типов с плавающей точкой определяется реализацией компилятора. У чисел с плавающей точкой после точки какое-то определённое число значащих цифр, за значащами цифрами идут цифры, которые представляют собой информационный мусор, поэтому толку от них никакого нет.
В Borland C++ 3.1 для float выделяется 4 байта и даётся 7 значащих цифр после запятой, для double выделяется 8 байтов и даётся 15 значащих цифр после запятой.

  • В совокупности целочисленные типы и типы сплавающей точкой называются арифметическими типами.
  • Примеры Объявления переменной в программе:

  • При объявлении переменной можно указывать её значение

  • Имена переменным задают либо буквой, либо словом, состощим из букв латинского алфавита. Например, можно написать "int itog" – (целочисленная переменная "itog")
Если необходимо несколько переменных одного типа, то при объявлении оных можно разделять их запятыми:


  • Когда указываем переменные, в окончании обязательно ставим точку с запятой

Для закрепления материала можно выполнить простое упражнение:

1. Объявите две переменные и присвойте им значения.
2. Поменяйте значения, хранимые в переменных.
3. Попробуйте поменять местами переменные одинакового и различного типов, посмотрите, как ведет себя компилятор в различных ситуациях.

Например, вы объявили a=5; b=10. Необходимо сделать так, чтобы при выводе значения b на монитор выводилось число 5, а при выводе значения a число 10.

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

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

Чтобы программа могла что-то сделать, программе нужен доступ к какому-либо участку памяти компьютера. Например, чтобы выполнить простой расчет суммы из двух слагаемых, программе нужно место под хранение первого слагаемого, второго слагаемого и место под хранение полученного результата. Т. е. для вычисления суммы может требоваться либо два, либо три участка памяти (если используется два, то результат записывается поверх использованного слагаемого). Результат вычисления часто необходим для дальнейшего вычисления, в том числе для повторяемых вычислений. Вот так выглядит простейшая простая программа вычисления суммы:

Подход написания кодов подобным образом ведёт к тому, что нет возможности сохранять результаты для дальнейшего их использования. Вот получили мы в результате вычисления число 15, а как этот результат использовать дальше? Числа 5 и 10 в этом примере являются литеральными константами: они где-то сохранены в памяти ПК, иначе бы вычисление не представлялось возможным, но повторно обратиться к 5 и 10 мы уже не можем, потому что непосредственно с этими литеральными константами способа связи нет. Только считать заново.
Кроме этого, во время работы подобной программы вводить значения для вычислений с клавиатуры нельзя.
Поэтому, чтобы программы были полноценными, программисты почти всегда используют переменные. Редкая программа может оказаться полезной, если переменных в ней вобще нет.
Улучшение программы может быть таким:



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


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

При именовании переменных нужно иметь в виду следующее:

  • Первым символом имени переменной не может быть цифра
  • Имя переменной может состоять только из символов латинского алфавита, цифр и символа подчёркивания
  • Символы в верхнем и нижнем регистрах рассматриваются как разные
  • В качестве имени нельзя использовать ключевые слова, зарезервированные компилятором
  • Не стоит начинать название с одного или двух символов подчёркивания: подобные имена используются разработчиками для нужд компилятора, поэтому использования подобных имён способно привести к неожиданным последствиям
  • Стандарт не ограничивает длину задаваемого переменной имени, но некоторые платформы могут вводит свои ограничения на длину
Тип переменной определяет, что именно в ней будет храниться. Хранимым значением может быть число, строка, какой-то наш собсвенный тип данных. Все типы, даже одинаковые, но с разным названием, воспринимаются компиляторами C++ как типы с разной структурой, т. е. считаются разными, поэтому у разных типов переменных могут различаться операции, которые можно использовать.

Так, например, если переменная имеет целочисленный тип, то для нее определена операция сложения +
Если переменная имеет тип "массив символов", то операции сложения + в таком типе нет. Если попробовать сложить символьные строки char* (не путайте со string), используя +, то ничего из этого не получится.


Каждый тип может имеет свои особенности, поэтому при создании переменных вы должны правильно выбирать соответствующий им тип.
В C++ Имеется важное отличие между понятиями определения и объявления переменной.

Под объявлением понимается, собственно, задание имени переменной и указание ей нужного типа.
Под определением понимается внесение какой-то информации в объявленную переменную.
  • Размеры переменных зависят от вашей операционной системы. Чтобы посмотреть размер переменной, для нас существует оператор sizeof. Этот оператор имеет некоторую особенность, на которую в дальнейшем натыкаются многие новички:
    • Операция sizeof, применяемая к указателю отдаёт размер указателя, а не размер того, на что указатель указывает
Об указателях рано рассказывать, но имейте в виду, что у sizeof имеется особенность, связанная с указателями

Иногда хочется узнать, какое максимальное и минимальное значение можно обрабатывать в переменной арифметического типа. В действительности эти значения зависят от платформы, в стандартной библиотеке C++ максимумы и минимумы реализованы в шаблоне numeric_limits. Числовые пределы заменяют и дополняют обычные препроцессорные константы языка С. Впрочем, эти константы по-прежнему доступны для целочисленных типов в заголовочный файлах <climits> и <limits.h>, а для вещественных типов — в заголовочный файлах <float> и <float.h>
В компиляторе Borland C++ 3.1 можно найти файлы с описанными лимитами в папке, в которую установлен борланд. (У меня, например, эти файлы находятся в C:\Borland\BORLANDC\INCLUDE)
В компиляторе mingw, с большой вероятностью, в папке, в которую установлен mingw (У меня, например, S:\Program Files\CodeBlocks\MinGW\include
В других компиляторах можно попробовать найти по аналогии

Если вы смогли найти файлы лимитов, то при желании посмотреть вовнутрь них, открывайте эти файлы нормальными текстовыми редакторами (AkelPad, Notepad++ и т. п.). После открытия можно увидеть нечто похожее на:

Такая строчка обозначает, что компилятор может использовать константу INT_MAX, значение которой равно 2147483647.

В показанном примере к числу, которое для типа int по определению является последним, прибавляется единица. Из-за этого происходит переполнение, и, если компилятор не настроен, чтобы не компилировать код в подобной ситуации, то скорее всего выдаст предупреждение о переполнении и выполнит код, в результате работы которого в переменной окажется наименьшее значение: это как пройти по кругу. Такое переполнение опасно.
Просто код:

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


  • При смешивании знаковости будьте очень внимательны к обрабатываемым диапазонам значений
Объявлять явно знаковые и беззнаковые переменные можно двумя способами. Либо явно писать ключевые слова signed (unsigned), либо с помощью специального суффикса "u"


Просто код:



5 комментариев на «“Переменные в С++”»

  1. Николай:

    Спасибо за уроки, насколько я понял,  объект   cin.get() в конце программы должен дождаться нажатия ENTER, для окончания работы программы, но у меня для просмотра вывода работы программы её нужно продублировать, не могли бы Вы объяснить, почему?

     

    • Такое происходит из-за оставления символа ‘\n’ в потоке ввода.
      Происходит из-за смешения ввода: в поток ввода вводятся числа, потом туда запихивается символ. Нажатие Enter туда и влезает, поток съедает нажатие Enter. Т. е. Enter съелся = Enter нажат. То же, что дождался.

      Я не могу это хорошо объяснить. Как сумел. Вот некоторые решения такой проблемы:
      http://www.cyberforum.ru/cpp-beginners/thread1260162.html#post6641410

  2. Николай:

    Спасибо за помощь, разобрался.

    Вместо  cin.get(); cin.ignore(2);

    2 — количество игнорируемых символов.

  3. Сергей Григорьевич:

    Благодарю! Очень доходчиво. Но сразу не запомнить (мне).

  4. Crew200:

    пошел на обучение, много что не понял у вас все так расписано идеально, жму крепко руку ! спасибо

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

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

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/hel-fulton/programmirovanie-na-yazyke-ruby/?lfrom=15589587
Яндекс.Метрика