Компиляция ресурсов.
~~~~~~~~~~~~~~~~~~~~~
    Встроенный в С-- компилятор ресурсов по своим возможностям уступает
специализированным компиляторам ресурсов, но этих возможностей, как мне
кажется, будет достаточно для большинства Ваших задач.

    Будет проще перечислить то, что встроенный в C-- компилятор ресурсов не
умеет делать.  Не обрабатываются операторы ресурсов: 'VERSION', 'VERSIONINFO'
и определяемые пользователем ресурсы.  При необходимости, данные, вводимые с
помощью этих операторов, можно ввести с помощью оператора 'RCDATA'.  У многих
операторов ресурсов есть необязательные параметры 'loading' и 'memory'.
Поддержка этих параметров не реализована.  Встретив эти параметры, компилятор
их просто пропустит.

    Заставить компилятор C-- обрабатывать ресурсы можно двумя способами:

    1. Включить в свой проект директивой '#include' файл с расширением '.rc'.
Файлы с таким расширением компилятор считает файлом с ресурсами. Файл
ресурсов необходимо включать в Ваш проект лишь после включения заголовочных
файлов Windows.

    2. Ресурсы можно располагать в теле программы в произвольном месте, но
текст ресурсов должен начинаться с директивы '#pragma resource start', а
заканчиваться директивой '#pragma resource end'.  Ресурсы могут быть
разделенными на части и эти части можно располагать в любом удобном для Вас
месте (глупо располагать ресурсы в блоке комментариев и потом удивляться,
почему они не были откомпилированы).  Компилятор соберет эти части и
откомпилирует.

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

    Надписи на русском языке в ресурсах для консольной версии компилятора
надо делать в Windows-кодировке. Для DOS версии компилятора эти надписи надо
делать в DOS-кодировке.


Метки вне процедур.
~~~~~~~~~~~~~~~~~~~~
    Метки вне процедур фактически располагаются в области данных программы.
Если данные и код находятся в одном сегменте (а именно так организованна
программа, написанная на C--), то метки вне процедур становятся простым и
эффективным методом для получения расстояний между частями программы.

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


Расширение возможностей указателей.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Теперь указатели можно использовать при передаче параметров процедурам, а
в самих процедурах в качестве как локальных, так и параметрических
переменных.  Указатели можно также использовать в структурах.  Можно
использовать указатели на указатели.  Введена поддержка указателей на
процедуры:

void (*proc)();  //объявление указателя на процедуру

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

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


Объявление процедур в структурах.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    С введение поддержки объявления процедуры в структуре, структура
становится подобной классу в C++.  Т.е. такая процедура становится методом
класса. Пример:

struct Point  // объявление класса
{
	int x; // элементы данных
	int y; // класса типа Point
	void SetX(int);  // объявление методов
	void SetY(int);  // класса Point
};

void Point::SetX(int _x)  //определение процедуры класса Point
{
	IF((_x>=0)&&(_x<=MAX_X)) x=_x;
// переменные x, y являются членами этого класса и поэтому доступ к ним из
// процедур этого же класса осуществляется напрямую.

 }

void main()
Point p;  //определяем структуру в стеке
{
  p.y = p.x = 0;
  p.SetX(1);
}

    При вызове процедуры являющейся методом класса ей неявным образом
передается адрес этого класса (структуры).  В самой процедуре этот адрес
доступен через имя параметрической переменной 'this'.  Эту переменную
автоматически генерирует компилятор.  Если в объявление процедуры в структуре
указать ключевое слово 'static', то такой процедуре адрес класса не
передается и переменная 'this' не генерируется.

    Процедура объявленная в структуре может быть динамической.  Для этого,
при ее определении, в самом ее начале, надо написать символ двоеточия ':'
(также как и для обычных динамических процедур).  Но такая динамическая
процедура не может быть использована как макрос.


Наследование.
~~~~~~~~~~~~~~
    В C-- поддерживаются простые и множественные наследования.  Объявление
структуры с наследованием имеет следующий синтаксис:

struct Derived : Base1, Base2, ... Basen
{
  int x0;
};

    Число базовых структур в производном не ограничено.  При множественном
наследовании структура может наследовать два и более экземпляра базовой
структуры. При этом возникает неоднозначность. Пример:

struct A
{
  int x,y;
  . . .
};

struct B : A  //структура 'B' наследует 'A'
{
  . . .

};

struct C : A  //структура 'C' наследует 'A'
{
  . . .
};

struct D : B, C //структура 'D' наследует 'B' и 'C'
{
  . . .
};

void main()
D d;  //выделяем для структуры 'D' память в стеке и присваиваем ей имя 'd'
{
  d.x0=0;

    В этом примере структура 'D' наследует два экземпляра структуры 'A' и в
ней находятся два элемента с именем 'x0'.  Компиляторы C++ при записи типа
'd.x0=0' выдают сообщение об ошибке.  C-- эту запись обрабатывает,
присваивание производится по умолчанию в элемент из последней базовой
структуры, имеющей элемент 'x0'.  Для того чтобы получить доступ ко второму
элементу 'x0' (физически этот элемент находится в структуре первым),
необходимо применить операцию разрешения видимости:

  d.B::x0=0;

    Из всего этого следует, что записи:

  d.x0=0;
и
  d.C::x0=0;

     являются равнозначными.


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

int proc (int param1, param2, param3)
{
  (e)BX = param3;
  (e)BX.TEG_STRUCT.var = proc2 (param1,papra2);
  proc3 (param1,param2);
}

    В этом примере параметр param3 используется лишь для того, чтобы
инициализировать регистр (e)BX, поэтому его можно сразу передать через
регистр:

int proc (int param1, param2, (e)BX)
{
  (e)BX.TEG_STRUCT.var = proc2 (param1,papra2);
  proc3 (param1,param2);
}

    Как Вы видите, процедура немного упростилась.

    В принципе порядок расположения стековых и регистровых параметров не
принципиален.  Но надо помнить, что содержимое регистров может быть легко
разрушено, и поэтому лучше всего регистровые параметры инициализировать лишь
после того, как были засунуты в стек все стековые параметры.  Для процедур
типа 'pascal' регистровые параметры лучше располагать после стековых
параметров.  Для процедур типа 'cdecl' и 'stdcall' сначала лучше располагать
регистровые параметры.


Присваивание одного значения нескольким переменным.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Если Вам необходимо присвоить нескольким переменным одинаковые значения:

  var1=0;
  var2=0;
  var3=0;

    то теперь это можно записать более коротко:

  var1=var2=var3=0;

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


Ключевое слово 'static' и оператор '::'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Если перед объявлением глобальной переменной, структуры или процедуры
указать слово 'static', то эти переменная, структура или процедура будут
доступны только в том файле, в котором они были объявлены.  Т.е. если Вы
включите этот файл в другой директивой 'include', то переменные объявленные
во включаемом файле со словом 'static' не будут доступны в основном файле, и
Вы можете в основном файле объявить другие переменные с такими же именами.

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

    Слово 'static' можно применять к любому глобальному объекту (переменной,
структуре, процедуре).  Для локального использования это слово можно
применять только к переменным.

    Если в Вашей программе есть глобальная и локальная переменная с
одинаковыми именами, то в процедуре, в которой объявлена эта локальная
переменная, Вы не имели доступа к одноименной глобальной переменной.  Теперь,
применив перед именем переменной оператор '::', Вы получите доступ к
глобальной переменной.  Пример:

int var;  //объявляем глобальную переменную

void proc()
int var;  //объявляем локальную переменную с именем уже существующей
          //глобальной переменной
{
  (e)AX=var;	//имеем доступ только к локальной переменной
  (e)AX=::var;  //а так можно получить доступ к глобальной переменной
}


Замена 'return' на 'goto'.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    В некоторых ситуациях, при компиляции программы, оператор 'return' будет
заменяться на 'goto'.  Это происходит при разрешенной оптимизации по размеру
кода для операторов 'return', которые расположены внутри процедуры и,
естественно, если размер кода для выполнения 'return' больше, чем размер кода
для реализации 'goto'.  Для динамических процедур, которые используются как
макросы, такая замена будет производится всегда.  Оператор 'goto' будет
выполнен на конец процедуры, там, где будет располагаться единственный выход
из процедуры.  В динамических процедурах, используемых в качестве макросов,
'return' в конце процедуры будет пропущен компилятором.

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

    Для оператора 'goto' существует его более короткий аналог - 'GOTO'.  Для
получения более компактного кода для оператора 'return' введен также более
короткий оператор 'RETURN'.  Его можно использовать, если от места его
применения до конца процедуры находится не более 128 байт.  Если Вы будете
использовать 'RETURN' на большем расстоянии до конца процедуры, то компилятор
выдаст сообщение об ошибке.  При использовании 'return' на расстоянии меньше
128 байт до конца кода, компилятор выдаст вам предупреждение о возможном
использовании 'RETURN'.


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

    Объявление битового имеет следующий синтаксис:

<тип> [<идентификатор>]:<константа>;

или на примере:

int var:5;  //объявление битового поля размером 5 бит с именем 'var'

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

    <идентификатор> именует битовое поле.  Его наличие необязательно.
Неименованное битовое поле означает пропуск соответствующего числа битов
перед размещением следующего элемента структуры.  Неименованное битовое поле,
для которого указан нулевой размер, имеет специальное назначение: оно
гарантирует, что память для следующего битового поля будет начинаться на
границе того типа, который задан для неименованного битового поля.  Т.е.
будет произведено выравнивание битового поля на 8/16/32 бита.

    В C-- все битовые поля упаковываются одно за другим независимо от границ
типа идентификаторов.  Если последующее поле не является битовым полем, то
оставшиеся до границы байта биты не будут использованы.  Максимальный размер
битового поля равен 32 бита для типа dword/long, 16 бит для типа word/int и 8
бит для типа byte/char.  Битовые поля можно объединять, т.е. использовать их
в операторе 'union'.  'sizeof' примененный к битовому полю вернет размер
этого поля в битах.  При использовании битового поля, его содержимое будет
расширятся в регистр как беззнаковое целое число.



