//Оглавление

Переменные

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

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

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

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

В С++ область видимости переменной – область кода в которой символическое имя доступно для использования. Это может быть программа целиком, в таком случае переменная называется глобальной, модуль, функция,  класс, пространство имен, или же просто область кода, заключенная в парные фигурные скобки {}.

В дополнение к стандартному набору операций, определяемых типом переменной, синтаксис языка С++ позволяет определить у переменной дополнительные свойства, так называемые спецификаторы типа (в англоязычной документации «type specifiers»). которые представляют собой инструкции компилятору на предмет того, как должно контролировать использование переменной, объявленной с соответствующим спецификатором. В С++ рычагов воздействия на компилятор два, const и volatile.

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

Ключевое слово const, указанное при декларации переменной, сообщяет компилятору о том, что значение переменной не должно изменятся после ее инициализации, соответственно, любой код изменяющий значение этой переменной будет трактоваться компилятором как ошибочный. Основное применение константных переменных - мнемоническое обозначение констант, например константная переменная «много» может обозначать «сто» или «десять миллионов». Использование перечислений для объявления констант не всегда оправданно, а использование препроцессора может привести к ряду хорошо известных проблем одна из которых описана ниже.

Допустим вы разрабатываете некую библиотеку, и поставляете ее в виде пары library.lib и заголовочного файла interface.h. В interface.h вы декларируете константу, скажем версию библиотеки

#define VERSION 1

Пользователь вашей библиотеки, включает заголовочный файл interface.h в один из своих заголовочных файлов, или в stdafx.h, а в одном из .cpp файлов декларирует такой вот класс.

class Function
{
public:
  enum 
  {
    VERSION, 
    TYPE
  };
  //...
};

Сколько времени потратит он на то чтобы понять почему его программа не компилируется с такой вот пачкой ошибок

error C2143: syntax error : missing '}' before 'constant'
error C2143: syntax error : missing ';' before '}'
error C2238: unexpected token(s) preceding ';'
error C2059: syntax error : '}'
error C2143: syntax error : missing ';' before '}'
error C2059: syntax error : '}'

сильно зависит квалификации, попробуйте угадать. Можете также пофантазировать, между какими животными, существующими или же вымышленными, и вами, как разработчиками библиотеки, будет он строить ассоциации когда обнаружит причину. Если нет возможности исправить файл, в котором определена директива препроцессора, ошибка можно исправить следующим образом.


#ifdef VERSION
#undef VERSION
#endif

class Function
{
public:
  enum 
  {
    VERSION, 
    TYPE
  };
  //...
};

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


class MassCalc
{
public:
  MassCalc(double volume, double density):_dMass(density * volume)
  {
  	// инициализация переменной _dMass в теле конструктора
  	// а не в списке инициализации приведет к ошибке компиляции
  	// _dMass = density * volume;
  }
  const double _dMass;
};

void main()
{
  MassCalc water(1000, 1000);
  MassCalc iron(1000, 7800);
}

В языке С++ константные переменные инициализируются непосредственно в момент декларации, константные поля классов - в списке инициализации конструктора, константные статические поля классов - во время реализации этих полей. Несмотря на то, что значения константных переменных предполагаются неизменными, средства языка С++ позволяют изменять значения таких переменных, убрав спецификатор const с помощью оператора const_cast, либо с помощью оператора приведения типов ().

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

В языке C# понятие константности несколько расширено, по сравнению с С++. Константная переменная в C#, декларируемая так же как в С++ посредством ключевого слова const, в терминах С++, является константной статической переменной, т.е. ее значения одинаковы для всех экземпляров класса. Константой переменной экземпляра в С# является "readonly" переменная. Значения таких переменных инициализируются в момент создания экземпляра. В языке Java константными переменнымя являются переменные обявленные с помощью final

volatile переменные

Ключевое слово volatile есть указание компилятору не оптимизировать использование данной переменной. Один из интересных примеров использования volatile переменных описан в книге "Защищенный код".  Предположим мы разрабатываем «Очень Надежную Программу». В одном из мест мы добываем «Очень Секретные Данные». После использования данных буфер с ними необходимо обнулить, но код по обнулению . Отключить оптимизации так же можно с помощью препроцессора

void f(char *pBuffer)
{
  memcpy(pBuffer, "Во Владивостоке идут мокрые дожди тчк Свирепые ежики идут на север тчк");
}
#pragma optimize("", off)
#pragma optimize("", on)

Компилятор позволяет декларировать переменную одновременно как const и volatile, но это, по-моему, какой-то дремучий постмодернизм.