Переменные

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

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

Переменные должны быть объявлены перед их использованием. Для идентификации переменных используются уникальные имена. Описания переменных используются для их определения и объявления типов. Описание не является оператором.

Основными типами являются:

  • int — целые числа;
  • bool — логические значения true и false;
  • string — символьные строки;
  • double — числа двойной точности с плавающей точкой.

Примеры:

string MessageBox;
int Orders;
double SymbolPrice;
bool bLog;

Дополнительные типы:

  • color — целое число, представляющее RGB-цвет;
  • datetime — дата и время, беззнаковое целое число, содержащее количество секунд, прошедших с 0 часов 1 января 1970 года.

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

Примеры:

datetime time_start = D'2004.01.01 00:00';
color my_color = C'0x64,0xF4,0xA6';

Массивы

Массив — это индексированная совокупность однотипных данных:

int a[50];       // Одномерный массив из 50 целых чисел.
double m[7][50]; // Двухмерный массив из семи массивов,
                 // каждый из которых состоит из 50 чисел.

Индексом массива может быть только целое число. Допускаются не более чем четырехмерные массивы. Нумерация элементов массива начинается с 0. Последний элемент одномерного массива имеет номер на 1 меньший, чем размер массива, то есть обращение к последнему элементу массива из 50 целых чисел будет выглядеть как a[49]. То же самое относится и к многомерным массивам — индексация одного измерения производится от 0 до размер измерения-1. Последний элемент двумерного массива из примера будет выглядеть как m[6][49].

При доступе за пределы массива исполняющая подсистема сгенерирует ошибку ERR_ARRAY_INDEX_OUT_OF_RANGE (4002), которую можно получить при помощи функции GetLastError().

Локальные переменные

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

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

 

Пример:

int my_func()
{
   int return_code=0;
   ....
   return(return_code);
}

Формальные параметры

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

Пример:

void my_func(int x[], double y, bool z)
{
   if(y>0.0 && !z)
   Print(x[0]);
   ...
}

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

Пример:

void my_func(int x, double y = 0.0, bool z = true)
{
   ...
}

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

Пример:

my_func(216, 2.5);

Библиотечные функции, импортируемые в других модулях, не могут иметь параметров по умолчанию.

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

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

Пример:

void my_func(int& x, double& y, double& z[])
{
   double calculated_tp;

   ...

   for(int i=0; i<OrdersTotal(); i++)
   {
      if(i==ArraySize(z)) break;
      if(OrderSelect(i) == false) 
         break;
      z[i]=OrderOpenPrice();
   }

   x=i;
   y=calculated_tp;
}

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

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

В функцию нельзя передать больше 64 параметров

Статические переменные

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

Пример:

void my_func(int x[], double y, bool z)
{
   if(y>0.0 && !z)
   Print(x[0]);
   ...
}

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

Пример:

void my_func(int x, double y = 0.0, bool z = true)
{
   ...
}

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

Пример:

my_func(217, 4.2);

Библиотечные функции, импортируемые в других модулях, не могут иметь параметров по умолчанию.

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

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

Пример:

void my_func(int& x, double& y, double& z[])
{
   double calculated_tp;

   ...

   for(int i=0; i<OrdersTotal(); i++)
   {
     if(i==ArraySize(z)) break;
     if(OrderSelect(i)==false) break;
     z[i]=OrderOpenPrice();
   }

   x=i;
   y=calculated_tp;
}

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

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

В функцию нельзя передать больше 64 параметров

Глобальные переменные

Глобальные переменные определяются на том же уровне, что и функции, т. е. не локальны ни в каком блоке.

Пример:

int iGlobal = 20; // глобальная переменная 

void OnTick()
{
   ...
}

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

Замечание: не следует путать переменные, объявленные на глобальном уровне, с глобальными переменными клиентского терминала, доступ к которым осуществляется при помощи функций GlobalVariable…().

Внешние переменные

Глобальные переменные определяются на том же уровне, что и функции, т. е. не локальны ни в каком блоке.

Пример:

int iGlobal = 20; // глобальная переменная 
void OnTick() 
{
 ... 
}

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

Замечание: не следует путать переменные, объявленные на глобальном уровне, с глобальными переменными клиентского терминала, доступ к которым осуществляется при помощи функций GlobalVariable…().

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

Во время объявления переменных можно сообщить им значение путем помещения знака равенства и константы после имени переменной. Этот процесс называется инициализацией и в общем случае имеет вид:

тип имя_переменной — константа;

Переменные могут быть проинициализированы любым выражением, а не только константой.

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

Примеры:

int n = 1;
double mp      = MarketInfo(Symbol(),MODE_POINT);
string str     = "hello";
double fl[]    = { 0.0, 0.165, 0.712, 0.4, 0.384, 2.9 };
int adim[4][4] = { 1, 2, 1, 3, 2, 1, 2, 4, 1, 3, 5, 1, 7, 8, 8, 7 };

Список значений элементов массива должен быть заключен в фигурные скобки. Пропущенные инициализирующие значения считаются равными 0. Если размер инициализируемого массива не указан, то он определяется компилятором, исходя из размера инициализирующей последовательности. Многомерные массивы инициализируются одномерной последовательностью, последовательностью без дополнительных фигурных скобок. Массивы (в том числе и объявленные на локальном уровне) могут инициализироваться только константами

Описание внешних функций

Тип внешних функций, определенных в другом модуле, должен быть явно описан. Отсутствие такого описания может привести к ошибкам при компиляции, компоновке или выполнении программы. При описании внешнего объекта используйте ключевое слово #import с указанием модуля.

Примеры:

#import "user32.dll"
int MessageBoxA(int hWnd ,string szText,string szCaption,int nType);
int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
#import "lib.ex4"
double round(double value);
#import

С помощью импорта можно очень легко описывать функции, вызываемые из внешних DLL или скомпилированных EX4 библиотек.

Существует способ передавать в импортируемые dll-функции указатели на переменные. Данные типа string передаются как указатель на соответствующую область памяти (напомним, что внутреннее представление строковых данных состоит из двух частей: длины области памяти и указателя на область памяти). Если необходимо передать данные типа int или double, то в качестве параметра следует передать по ссылке одноэлементный массив соответствующего типа.

Пример:

#import "some_lib.dll"
void PassIntegerByref(int& OneInt[]);

#import

int start()
{
   int array[1];
   //...
   PassIntegerByref(array);
   Print(array[0]);
   //...
}