Speccy - наш выбор!

Speccy - наш выбор! (http://zx-pk.ru/index.php)
-   Эмуляторы отечественных компьютеров (http://zx-pk.ru/forumdisplay.php?f=61)
-   -   Эмулятор УКНЦ (http://zx-pk.ru/showthread.php?t=6257)

hobot 24th October 2012 15:09

Quote:

Originally Posted by Patron (Post 547565)
Я тоже только на днях обнаружил

О том и речь ) Благодарю, Patron !
Поэтому я и предложил пускай пользователь имеет возможность либо определить
путь сохранения в ini файле или допустим в буфер системы ?
Quote:

Originally Posted by Patron (Post 547565)
Приходится запоминать текущий каталог сразу после запуска эмулятора

Или как-то так наверное даже правильней?

hobot 11th December 2012 23:41

прилеплю сюда что-бы не забылось\потерялось, может будет время что бы посмотреть в чём там проблема с запуском?

Спасибо.

Vamos 27th January 2013 20:49

1 Attachment(s)
На текущий момент мыслей по поводу реализации прерываний нет, поэтому пока то что есть: работающий С2 и СА оба пока не работают по прерываниям.
По С2 можно загрузиться с НХ сервера, по СА загрузка останавливается с ошибкой, но тоже результат :) .
Для связи используется программа сом0сом http://sourceforge.net/projects/com0com/
Все остальное в ветках "Сеть УКНЦ" и "УКНЦ загрузка через стык С2"
Для сети запуск копий из разных папок.

nzeemin 28th January 2013 03:25

Затащил к себе код от Vamos, и озаботился настройкой COM-портов -- уже жаловались что приходится менять код под себя. Не доделал ещё, но будет примерно так: отдельный диалог на редактирование структуры DCB. Если какие-либо ещё параметры DCB нужно вытащить в редактор -- скажите, сделаю.

http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx -- DCB structure

http://img-fotki.yandex.ru/get/5642/..._dc87e392_orig

Vamos 28th January 2013 03:33

Наверное это лишнее, в реале УКНЦ кроме скорости стыка С2 все жёстко определено.

hobot 28th January 2013 20:08

nzeemin, если будет возможность - посмотри пожалуйста ещё раз про звук для свежей компиляции UKNCBTL. Штука такая - на обычном DESKTOPE у меня бортовой звук и там все норм работает, а на ноуте UKNCBTL портит настройку так, что приходиться лазить поправлять иначе такое в колонках шипение при запуске других приложений пугающее ))) Впрочем я привык уже после запуска эмулятора лазить автоматом в звук.настройки ноута ))) Проблема в том, что минимальное значение ползунка почему то на звуковухе бука вызывает перегруз в купе с переключением на (только) левый канал. Какие ещё доработки планируются?
Возможно ли ожидать Load State в обозримом будущем и в целом любые новости по этому проекту всегда очень интересно !

Patron 30th January 2013 12:56

Для реализации прерываний портов СА и С2 нужно модифицировать не только функцию void CFirstMemoryController::SetPortWord(WORD address, WORD word), но и void CFirstMemoryController::SetPortByte(WORD address, BYTE byte), которая в данный момент выглядит довольно бледно:

Code:

void CFirstMemoryController::SetPortByte(WORD address, BYTE byte)
{
    WORD word = (address&1)?((WORD)byte) << 8:(WORD)byte;
    switch (address) {
        case 0176560: //network
        case 0176561: //СА: Регистр состояния приемника
            m_Port176560 = (m_Port176560 & ~0100) | (word & 0100);  // Bit 6 only
            break;
                case 0176562: // СА: Регистр данных приемника
        case 0176563: // недоступен по записи
            return ;
                case 0176564: // СА: Регистр состояния источника
        case 0176565:
            m_Port176564 = (m_Port176564 & ~0105) | (word & 0105);  // Bits 0,2,6
            break;
                case 0176566: // СА: Регистр данных источника
        case 0176567: // нижние 8 бит доступны по записи
            m_Port176566 = word & 0xff;
            m_Port176564 &= ~128;  // Reset bit 7 (Ready)
            break;

        case 0176570:  // Стык С2: Регистр состояния приемника
        case 0176571:
        case 0176572:  // Стык С2: Регистр данных приемника
        case 0176573:
        case 0176574:  // Стык С2: Регистр состояния источника
        case 0176575:
        case 0176576:  // Стык С2: Регистр данных источника
        case 0176577:
            return ;
    }
}



---------- Post added at 10:56 ---------- Previous post was at 10:29 ----------

Code:

void CFirstMemoryController::SetPortByte(WORD address, BYTE byte)
{
    WORD word = (address&1)?((WORD)byte) << 8:(WORD)byte;
    switch (address) {
        case 0176560: //network
        case 0176561: //СА: Регистр состояния приемника // Bit 6 only
            m_Port176560 = (m_Port176560 & ~0100) | (word & 0100); 
            break;
    }
}

Правильно ли я понимаю, что при использовании такого алгоритма обработки в эмуляторе байтовой записи в порт - команда CLRB @#176561 сбросит разрешение прерываний ?

Настоящая УКНЦ действительно преобразует байт в слово перед записью в порт ?

Vamos 30th January 2013 12:58

Patron, видимо nzeemin еще не затащил код, у меня там все прописано.
Но толку пока от этих прерываний мало, DLTST показывает что все хорошо, а загрузка как не шла так и не идет TU58 в том числе.

Patron 30th January 2013 13:02

Quote:

Originally Posted by Vamos (Post 571646)
DLTST показывает что все хорошо, а загрузка как не шла так и не идет TU58 в том числе.

DLTST пишет в порт слова. Запись слов мы вчера наладили. Но если программа пишет в порт байты - нужно налаживать void CFirstMemoryController::SetPortByte(WORD address, BYTE byte), а там просто мрак кромешный.

Vamos 30th January 2013 13:09

Quote:

Originally Posted by Patron (Post 571643)
Правильно ли я понимаю, что при использовании такого алгоритма обработки в эмуляторе байтовой записи в порт - команда CLRB @#176561 сбросит разрешение прерываний ?

Настоящая УКНЦ действительно преобразует байт в слово перед записью в порт ?

Вот не знаю, но команда MOVB @#176561,R5 проходит, номер станции работает.

---------- Post added at 12:09 ---------- Previous post was at 12:05 ----------

Quote:

Originally Posted by Patron (Post 571648)
DLTST пишет в порт слова. Запись слов мы вчера наладили. Но если программа пишет в порт байты - нужно налаживать void CFirstMemoryController::SetPortByte(WORD address, BYTE byte), а там просто мрак кромешный.

С этой функции все и началось, после того как я туда скопипастил из void CFirstMemoryController::SetPortWord(WORD address, WORD word) все для С2, стала работать загрузка НХ сервера.

Alex_K 30th January 2013 13:12

Quote:

Originally Posted by Patron (Post 571643)
Для реализации прерываний портов СА и С2 нужно модифицировать не только функцию void CFirstMemoryController::SetPortWord(WORD address, WORD word), но и void CFirstMemoryController::SetPortByte(WORD address, BYTE byte), которая в данный момент выглядит довольно бледно:

Code:

void CFirstMemoryController::SetPortByte(WORD address, BYTE byte)
{
    WORD word = (address&1)?((WORD)byte) << 8:(WORD)byte;
 ....................
}


Тут все значительно проще - 1801ВП1-065 сигнал WTBT не обрабатывает, при байтовой записи в 1801ВМ2 неиспользуемый байт устанавливается нулями, потому и есть такая строчка: WORD word = (address&1)?((WORD)byte) << 8:(WORD)byte;, которая делает целое слово, присутствующее на линиях адреса-данных. Достаточно вызвать SetPortWord с этим словом.

Patron 30th January 2013 13:38

Quote:

Originally Posted by Alex_K (Post 571653)
неиспользуемый байт устанавливается нулями

Тогда нужно просто добавить туда обработку прерываний.

...

Исправленный исходник требует дальнейших улучшений:

1. При установке разрешения прерывания в готовом регистре приёмника - прерывание возникает так же, как в передатчике, а регистры приёмников почему-то остались неисправленными:

Code:

void CFirstMemoryController::SetPortWord(WORD address, WORD word)
{
    switch (address) {
        case 0176560: //network
        case 0176561: // СА: Регистр состояния приемника // Bits 2,6 only
            m_Port176560 = (m_Port176560 & ~0104) | (word & 0104);
            break;
        case 0176570: // Стык С2: Регистр состояния приемника
        case 0176571: // Bit 6 only
            m_Port176570 = (m_Port176570 & ~0100) | (word & 0100);
            break;
    }
}


2. Приоритеты IRQ портов СА и С2 в файле Board.cpp остались неправильными:

Code:

m_pCPU->InterruptVIRQ(3, 0370);
m_pCPU->InterruptVIRQ(3, 0374);
m_pCPU->InterruptVIRQ(3, 0360);
m_pCPU->InterruptVIRQ(3, 0364);



---------- Post added at 11:31 ---------- Previous post was at 11:22 ----------

Запись байта в регистр данных передатчиков СА и С2 обрабатывается так:

Code:

void CFirstMemoryController::SetPortByte(WORD address, BYTE byte)
{
    WORD word = (address&1)?((WORD)byte) << 8:(WORD)byte;
    switch (address) {

        case 0176566: // СА: Регистр данных источника
        case 0176567: // нижние 8 бит доступны по записи
            m_Port176566 = word & 0xff;
            m_Port176564 &= ~128;  // Reset bit 7 (Ready)
            break;

        case 0176576:  // Стык С2: Регистр данных источника
        case 0176577:
            return ;
    }
}

Почему такая разница ?
Как записываемый в регистр данных С2 байт попадает в переменную m_Port176576 ?
Правильно ли, что при записи байта в регистр данных передатчика С2 - бит готовности в слове состояния не сбрасывается ?

---------- Post added at 11:38 ---------- Previous post was at 11:31 ----------

Ещё ошибка:
Code:

m_pProcessor->InterruptVIRQ(8, 0364);
Должно быть:
Code:

m_pProcessor->InterruptVIRQ(10, 0364);

Vamos 30th January 2013 13:39

Quote:

Originally Posted by Patron (Post 571658)
Как записываемый в регистр данных С2 байт попадает в переменную m_Port176576 ?

http://zx-pk.ru/showpost.php?p=571646&postcount=568

Меня смущает вот это m_Port176564 &= ~128; // Reset bit 7 (Ready)
я думаю должно быть так m_Port176564 &= ~0200; // Reset bit 7 (Ready)

Patron 30th January 2013 13:42

У всех прерываний должны быть разные приоритеты IRQ ( для С2 - приемник 7, передатчик 8, для СА - приемник 9, передатчик 10 ), иначе прерывания могут теряться.

---------- Post added at 11:42 ---------- Previous post was at 11:40 ----------

Quote:

Originally Posted by Vamos (Post 571662)
Меня смущает вот это

128 == 0200 (проверил при помощи калькулятора).
Но лучше, конечно, везде писать 0200 - тогда легче понять о чём речь.

Vamos 30th January 2013 13:46

Quote:

Originally Posted by Patron (Post 571663)
128 == 0200 (проверил при помощи калькулятора).

Я имел ввиду другое, операция & побитовая и при использовании 128 не сбросится ли бит 6 (0100).

Patron 30th January 2013 13:51

Quote:

Originally Posted by Vamos (Post 571666)
Я имел ввиду другое, операция & побитовая и при использовании 128 не сбросится ли бит 6 (0100).

Т.к. и 128, и 0200, и 0x80 - это одно и то же число ( 10000000b ), то при одинаковом их использовании и результат будет одинаковым.

Alex_K 30th January 2013 14:00

Quote:

Originally Posted by Vamos (Post 571666)
Я имел ввиду другое, операция & побитовая и при использовании 128 не сбросится ли бит 6 (0100).

Не не сбросит, перед этим делается инверсия операцией ~, поэтому из слова 128 получится слово 65407, оно же 177577, оно же 0xF7.

Titus 30th January 2013 14:02

Quote:

Originally Posted by Patron (Post 571663)
[/COLOR]128 == 0200 (проверил при помощи калькулятора).
Но лучше, конечно, везде писать 0200 - тогда легче понять о чём речь.

А чего, Си разве понимает восьмеричные числа?

Alex_K 30th January 2013 14:09

Quote:

Originally Posted by Titus (Post 571671)
А чего, Си разве понимает восьмеричные числа?

Titus, вы только проснулись? Для справки - язык Си изначально был сделан на PDP-11, поэтому так и похож на ассемблер PDP-11. Ну соответственно, т.к. на PDP-11 использовалась восьмеричная система, то использовалась она и в Си, достаточно число начать с нуля.

Titus 30th January 2013 14:20

Quote:

Originally Posted by Alex_K (Post 571672)
Titus, вы только проснулись? Для справки - язык Си изначально был сделан на PDP-11, поэтому так и похож на ассемблер PDP-11. Ну соответственно, т.к. на PDP-11 использовалась восьмеричная система, то использовалась она и в Си, достаточно число начать с нуля.

Я не проснулся, я просто не использую восьмеричную систему, и нигде, кроме PDP-систем ее не встречал) Она для меня чуждая) Близкая - десятичная и шестнадцатиричная. Поэтому все нюансы, связанные с ней мне не известны)
Мало того, видел много исходников на Си, встречаются шестнадцатиричные числа 0x..., но чтобы восьмеричные встретить - никогда такого не было)

Vamos 30th January 2013 14:21

Quote:

Originally Posted by Alex_K (Post 571672)
поэтому так и похож на ассемблер PDP-11.

Нуу.. после Макро11 он мне показался китайской грамотой, а сейчас там еще всякие объекты классы, мне компилятор чуть мозг не вынес сообщениями об ошибках когда я его три недели назад поставил впервые к себе на комп.
Хотя сейчас посмотрев на некоторые исходники Макро11, это конечно стилем называется, но помоему это очень много букв.

Alex_K 30th January 2013 14:22

Quote:

Originally Posted by Titus (Post 571676)
Я не проснулся, я просто не использую восьмеричную систему, и нигде, кроме PDP-систем ее не встречал) Она для меня чуждая) Близкая - десятичная и шестнадцатиричная. Поэтому все нюансы, связанные с ней мне не известны)
Мало того, видел много исходников на Си, встречаются шестнадцатиричные числа 0x..., но чтобы восьмеричные встретить - никогда такого не было)

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

Titus 30th January 2013 14:24

Quote:

Originally Posted by Alex_K (Post 571679)
Но ведь в любом руководстве по языку должно это быть описано. Надеюсь также, что EmuStudio наконец-то в консоли будет выдавать в восьмеричной системе.

Ну, если что опционально специально для любителей восьмеричной системы.

Alex_K 30th January 2013 14:25

Quote:

Originally Posted by Vamos (Post 571677)
Нуу.. после Макро11 он мне показался китайской грамотой, а сейчас там еще всякие объекты классы, мне компилятор чуть мозг не вынес сообщениями об ошибках когда я его три недели назад поставил впервые к себе на комп.
Хотя сейчас посмотрев на некоторые исходники Макро11, это конечно стилем называется, но помоему это очень много букв.

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

Titus 30th January 2013 14:26

Quote:

Originally Posted by Alex_K (Post 571679)
Но ведь в любом руководстве по языку должно это быть описано.

Да, но за ненадобностью никогда не обращал внимания.

Alex_K 30th January 2013 14:27

Quote:

Originally Posted by Titus (Post 571680)
Ну, если что опционально специально для любителей восьмеричной системы.

Ой!!! :eek_std: Неужели дождались?

Titus 30th January 2013 14:31

Quote:

Originally Posted by Alex_K (Post 571682)
С объектно-ориентированным программированием у меня тоже очень сложно. Так как я привык к ассемблеру и классическому Си, то я знаю, что делает программа, а с этими классами, методами много непоняток, они как бы сами в себе.

Согласен. Я тоже не люблю ООП. Когда работаешь с ассемблером или простым Си, прекрасно понимаешь, что ты делаешь конкретной функцией, и с каким типом данным работаешь. А это наследование и классы, уходящие к первоисточникам, набирая по пути дополнительных свойств и функций - это бррр... Для чего-то это может и удобно, но мне антагонистично)

---------- Post added at 13:31 ---------- Previous post was at 13:28 ----------

Quote:

Originally Posted by Alex_K (Post 571686)
Ой!!! :eek_std: Неужели дождались?

Не, ну не сейчас) У эмулятора же даже нет настроек, чтобы это включить)

Patron 30th January 2013 14:50

Quote:

Originally Posted by Alex_K (Post 571682)
я знаю, что делает программа, а с этими классами, методами много непоняток, они как бы сами в себе.

На самом деле смысл объектного программирования в своей основе вполне "ассемблерный" - объект это немного улучшенная обычная структура ( srtuct ), с тремя важными и полезными новшествами:

1. Добавлены две специальные функции "конструктор" и "деструктор", которые всегда (ну, или почти всегда) автоматически вызываются при создании и уничтожении такой "классной" структуры.

2. Членами могут быть не только данные, но и функции (их называют "методы"), и даже автоматически разыменуемые указатели на функции ( их называют "виртуальные методы" ).

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

Если никакие из этих возможностей не использовать - объект класса C++ будет ничем не отличим от экземпляра обычной структуры C.

Titus 30th January 2013 14:57

Quote:

Originally Posted by Patron (Post 571694)
Если никакие из этих возможностей не использовать - объект класса C++ будет ничем не отличим от экземпляра обычной структуры C.

Тогда и незачем особо использовать классы)
У меня, например, EmuStido написан практически на чистом Си, и прекрасно и удобно выглядит и работает)

Vamos 30th January 2013 14:59

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

Patron 30th January 2013 16:12

Quote:

Originally Posted by Titus (Post 571700)
Тогда и незачем особо использовать классы

Конструкторы - это просто песня. Т.к. в C++ все типы данных являются классами - конструктор можно задать для чего угодно. У меня почти все "обычные" структуры имеют конструкторы с пустым телом - просто устанавливающие для членов значения по умолчанию.

Например:
Code:

struct Point {
        int X;
        int Y;
        Point():
        X(0),
        Y(0)
        {}
};

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

Если хочется дополнительно иметь возможноcть явно задавать начальные значения членов при создании структуры - можно сделать так:

Code:

struct Point {
        int X;
        int Y;
        Point( int X0 = 0, int Y0 = 0 ):
        X(X0),
        Y(Y0)
        {}
};

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

Point A;
Point B(1,1);


Titus 30th January 2013 16:14

Quote:

Originally Posted by Patron (Post 571709)
У меня почти все "обычные" структуры имеют конструкторы с пустым телом - просто устанавливающие для членов значения по умолчанию.

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

Patron 30th January 2013 16:36

Quote:

Originally Posted by Titus (Post 571742)
Мне нагляднее, когда без классов - простые функции и простые данные.

C++ - это и есть практически "чистый ассемблер" в том виде, в котором он должен быть. Использовать все его возможности в полном объёме или не использовать - зависит от потребностей. По мере роста потребностей - растёт и объём используемых возможностей.

Важно лишь с самого начала понимать, что все без исключения возможности С++ - это практически всё тот же "чистый ассемблер" без каких-либо "наворотов".

Titus 30th January 2013 16:43

Quote:

Originally Posted by Patron (Post 571763)
Важно лишь с самого начала понимать, что все без исключения возможности С++ - это практически всё тот же "чистый ассемблер" без каких-либо "наворотов".

Я так не считаю)
Программировал и на С++ с классами когда-то, и на чистом Си, и для меня просто Си очень дружественный, а ООП - нет.

Patron 30th January 2013 16:55

Quote:

Originally Posted by Titus (Post 571768)
для меня просто Си очень дружественный, а ООП - нет.

То, что повсюду называют ООП - на мой взгляд - просто вывих мозга. Как можно писать в таком стиле я представить себе не могу. Именно безумный стиль "ООП" многие (как я понимаю) путают с сутью объектного подхода.

На самом деле программа, использующая объекты - это лишь упрощённый вариант программы без объектов.

Вот пример класса LockVarType, создающего объекты быстрой межпоточной синхронизации размером в одно слово:

Code:

#define DWORD_ALIGN    __declspec(align(4))
#define LOCK_VAR_TYPE  DWORD_ALIGN LONG volatile

class LockVarType {
public:
        LockVarType():dwLockVar(0){}
        inline dword IsLocked(){ return dwLockVar; }
        inline void  Lock( int nSleepMS = 0 )
        {
                while( InterlockedCompareExchange( &dwLockVar, 1, 0 ) ) { Sleep( nSleepMS ); }
        }
        inline void  UnLock() { dwLockVar = 0; }
        inline bool  TimedLock( dword uTimeOut_MS, int nSleepMS = 0 )
        {
                dword  uTC = GetTickCount();
                while( InterlockedCompareExchange( &dwLockVar, 1, 0 ) )
                {
                        if( GetTickCount() - uTC >= uTimeOut_MS ) { return false; }
                        Sleep( nSleepMS );
                }
                return true;
        }
        inline bool TryLock() { return !InterlockedCompareExchange( &dwLockVar, 1, 0 ); }

protected:
        LOCK_VAR_TYPE  dwLockVar;
       
};

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

Titus 30th January 2013 16:58

Quote:

Originally Posted by Patron (Post 571775)
Этот объект имеет после компиляции размер в одно слово.
Сделать межпоточную синхронизацию легче и проще вряд ли реально.

Эм... точно одно слово? Я вижу какие-то функции)

Patron 30th January 2013 17:18

Quote:

Originally Posted by Titus (Post 571776)
Эм... точно одно слово? Я вижу какие-то функции)

Это макросы, которые подставляются в код программы в тех местах, где пользователь хочет как-то использовать объект.

Например, чтобы включить, а потом выключить межпоточную блокировку пользователь пишет:
Code:

LockVar.Lock();
................
LockVar.UnLock();

А в код программы вставляется:
Code:

while( InterlockedCompareExchange( &dwLockVar, 1, 0 ) ) { Sleep(0); }
................
dwLockVar = 0;


Titus 30th January 2013 17:24

Quote:

Originally Posted by Patron (Post 571783)
Например, чтобы включить, а потом выключить межпоточную блокировку пользователь пишет:
Code:

LockVar.Lock();
................
LockVar.UnLock();


На простом Си я напишу LockVar() или UnlockVar()

Patron 30th January 2013 18:41

Quote:

Originally Posted by Titus (Post 571787)
На простом Си я напишу LockVar() или UnlockVar()

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

---------- Post added at 16:26 ---------- Previous post was at 16:23 ----------

Вот и получается, что разница между LockVar( &dwLockVar ) и LockVar.Lock() только в том, что при переносе кода из одного проекта в другой - не надо думать, что относится к блокировке, а что нет - всё необходимое уже "упаковано" в описание объекта.

---------- Post added at 16:41 ---------- Previous post was at 16:26 ----------

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

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

А можно в ANSI C задавать переменную цикла прямо в операторе for ?
Code:

for( int i = 0 ; i < 100 ; i++ )

Titus 30th January 2013 19:40

Quote:

Originally Posted by Patron (Post 571798)
А можно в ANSI C задавать переменную цикла прямо в операторе for ?
Code:

for( int i = 0 ; i < 100 ; i++ )

Да, это возможность удобная, и сам ее иногда использую. Хотя, стараюсь не злоупотреблять, чтобы не раскидывать обьявления по коду.
Так же в Си++ удобно, что можно писать преобразование типов, скажем, не k = (long)i, а k = long(i). Для наглядности иногда удобней.

Вот и все, чем я пользуюсь из Си++ )


All times are GMT +4. The time now is 02:55.

Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.