Пару вопросов
От: Calc Россия  
Дата: 05.08.03 17:25
Оценка:
1) Для чего это надо и какую пользу это даёт

#pragma pack (push, 1)
sruct ... {
    ...
    ...
}
#pragma pack (pop)


2) Тут недавно код предложили один, помогите разобраться

#include <iostream>
#include <fstream>

int main()
{
    using namespace std;

    // перенаправим clog в файл my.log
    ofstream log("my.log");
    streambuf* original_clog_buffer(clog.rdbuf(log.rdbuf()));

    clog << "My application has started successfully.\r\n";

    // ...

    clog << "My application shuting down...\r\n";

    // вернем clog оригинальный буфер
    clog.rdbuf(original_clog_buffer);

    return 0;
}


Ну в общем всё ясно, кроме:
Чем clog отличается от cerr (ну типа что clog использует буфер, но это както не очень много мне даёт, что за буфер, где буфер)
В общем запутался в этих строчках:
streambuf* original_clog_buffer(clog.rdbuf(log.rdbuf()));
...
clog.rdbuf(original_clog_buffer);

rdbuf что это функция? Которая меняет буферы? и возвращает указатель на текущий?
То есть в первой строке мы устанавливаем буфер для clog буфер от log, точнее перенаправляем.
Но вот я ни как не могу понять что значит original_clog_buffer();
В MSDN накопал похожий код, только вот такой
streambuf* original_clog_buffer = clog.rdbuf(log.rdbuf());

Как я понипаю разницы нет ни какой, то есть в нашем случае () равно =, то есть присваение.
Это так?
Как самому сделать подобное? (класс где вместо = можно использовать () )
Ну и на конец в чём разница clog, cerr, cout?
Re: Пару вопросов
От: YVR  
Дата: 05.08.03 18:05
Оценка:
Здравствуйте, Calc, Вы писали:

C>1) Для чего это надо и какую пользу это даёт

C>
C>#pragma pack (push, 1)
C>#pragma pack (pop)
C>


Определяет выравнивание элементов структур
Например

#pragma pack (push, 1) // сохранить текущее; установить выравнивание 1 байт
struct aaa {
 char m1, m2;
}; // sizeof(aaa) == 2
#pragma pack (pop) // восстановить сохраненное

#pragma pack (push, 4) // сейчас обычно такое умолчание
struct bbb {
 char m1, m2;
}; // sizeof(bbb) == 8
#pragma pack (pop)



C>2) Тут недавно код предложили один, помогите разобраться

C>Чем clog отличается от cerr (ну типа что clog использует буфер, но это както не очень много мне даёт, что за буфер, где буфер)

Буферизация в обычно сильно ускоряет ввод/вывод (типа кеша)
Не перемешивать вызовы clog и cerr — будут чудеса

C>Как я понипаю разницы нет ни какой, то есть в нашем случае () равно =, то есть присваение.

C>Это так?

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

C>Ну и на конец в чём разница clog, cerr, cout?


clog==cerr с точностью до буферизации.
Т.е. clog заточен под большой объем вывода "ошибок" на консоль.
A cout — это для вывода "обычной" информации на консоль.
Разделение позволяет перенаправить информацию одной "значимости",
что здесь и было сделано — с консоли в файл.
Re: Пару вопросов
От: size_t Россия  
Дата: 05.08.03 18:13
Оценка:
> 1) Для чего это надо и какую пользу это даёт
>
>
> #pragma pack (push, 1)
> sruct ... {
>     ...
>     ...
> }
> #pragma pack (pop)
>


Это все для упаковки членов класса и экземпляров класса в памяти. Каждый класс занимает объем памяти кратный константе упаковки.
Представь что у тебя в одном классе 6 переменных типа char.
*Пример из MSDN*
struct s
{
   int i;      //выровнен на байт 0, размер 4
   short j;      //выровнен на байт 4, размер 2
   double k;   //выровнен на байт 8, размер 8
};

Это при упаковке по 4 байта. Между j и k есть целых(!) два байта пустого и неиспользованного пространства
При упаковке по одному байту они будут плотно прилегать друг к другу. Это несколько неприятно будет для k — ее будет тяжело прочитать так как она 8 байтная, но не выровнена на 8 байтовую границу.
А синтаксис с прагмами — это для удобства. Первая прагма push сохраняет текущие настройки в стеке и выставляет этот параметр в 1. Вторая прагма восстанавливает настройки из стека.

>

> 2) Тут недавно код предложили один, помогите разобраться
>
>
> #include <iostream>
> #include <fstream>
> 
> int main()
> {
>     using namespace std;
> 
>     // перенаправим clog в файл my.log
>     ofstream log("my.log");
>     streambuf* original_clog_buffer(clog.rdbuf(log.rdbuf()));
> 
>     clog << "My application has started successfully.\r\n";
> 
>     // ...
> 
>     clog << "My application shuting down...\r\n";
> 
>     // вернем clog оригинальный буфер
>     clog.rdbuf(original_clog_buffer);
> 
>     return 0;
> }
>

>
clog cerr cout — это три разных предопределенных потока для разных назначений. При желании можно будет завести три консольных окна для вывода и выводить их по отдельности... В одном окне будут сообщения об ошибках, в другом логи исполнения программы, а в третьем пользовательский вывод. (а cin сделать клавиатурным вводом с удаленной машины 8)
Теперь по коду. Эта rdbuf принимает новый буффер и отдает пользователю на растерзание старый.
А вот то что было со скобочками и равенствами — это далеко не присваивания. Это конструкторы копирования. (хоть это и чуть чуть похоже на присваивание)
Буффер нельзя создать просто так... надо сразу (при конструкции) дать куда выводить все то что у него накопится, вот по этому тут такая сложная конструкция.
Если отобрать просто так буффер у потока, то потом его никто не уничтожит! Поэтому его нужно отобрать, сохранить и вернуть назад когда он больше не нужен. В случае вин32 это не так и страшно (ну, повиснет там программа когда закрываться будет и делов-то), а вот в случае дос — это могло привести к плохим последствиям.
Здесь проведено примерно следующее: стандартный буффер clog был подменен буффером от log, а старый стандартный буффер clog был сохранен в original_clog_buffer прозапас. В конце его отдали назад. За буффер log можно не беспокоиться, его пришибет log самостоятельно...

Кто скажет что это девочка, пусть первым бросит в меня камень! (с)О.Бендер
Posted via RSDN NNTP Server 1.7 beta
----------------
Нужное вписать.
Re[2]: Пару вопросов
От: Calc Россия  
Дата: 05.08.03 18:15
Оценка:
Здравствуйте, YVR, Вы писали:

А как выравнивание влияет на выполнение программы?
Re[2]: Пару вопросов
От: Calc Россия  
Дата: 05.08.03 18:26
Оценка:
Здравствуйте, size_t, Вы писали:

_>clog cerr cout — это три разных предопределенных потока для разных назначений.

Ну это я знаю, а с физической стороны скажем можно вместо cout использовать cerr или clog (ну конечно так делать ни кто не будет, но всё же)
Вроде они классы. Вроде у них общий родитель.

И вообще где можно подробно прочесть о членах этих так называемых классов?
Re: Пару вопросов
От: MaximE Великобритания  
Дата: 05.08.03 18:35
Оценка:
Здравствуйте, Calc, Вы писали:

C>2) Тут недавно код предложили один, помогите разобраться


C>
C>#include <iostream>
C>#include <fstream>

C>int main()
C>{
C>    using namespace std;

C>    // перенаправим clog в файл my.log
C>    ofstream log("my.log");
C>    streambuf* original_clog_buffer(clog.rdbuf(log.rdbuf()));

C>    clog << "My application has started successfully.\r\n";

C>    // ...

C>    clog << "My application shuting down...\r\n";

C>    // вернем clog оригинальный буфер
C>    clog.rdbuf(original_clog_buffer);

C>    return 0;
C>}
C>


C>Ну в общем всё ясно, кроме:

C>Чем clog отличается от cerr (ну типа что clog использует буфер, но это както не очень много мне даёт, что за буфер, где буфер)

По-умолчанию, буферы потоков clog, cerr, cout пишут в стандартный поток stdout. Этот поток по-умолчанию направлен в консоль.

В стандартной библиотеке форматированный и неформатированный ввод/вывод осуществляется разными классами. Классы-наследники std::basic_streambuf<> содержат функции только для неформатированного ввода/вывода. Классы std::basic_ostream<>, std::basic_istream<>, std::basic_iostream<> агрегируют экземпляр std::basic_streambuf<>, занимаются форматированием и пишут/читают свои буферы. Буфер отвечает за то, куда/откуда будут поступать данные. Заменив у потока буфер другим буфером мы направляем ввод/вывод потока в этот другой буфер.

C>В общем запутался в этих строчках:

C>
C>streambuf* original_clog_buffer(clog.rdbuf(log.rdbuf()));

// тоже самое, что и
streambuf* original_clog_buffer = clog.rdbuf(log.rdbuf());

C>...
C>clog.rdbuf(original_clog_buffer);
C>

C>rdbuf что это функция? Которая меняет буферы? и возвращает указатель на текущий?

Это перегруженная функция:

_Mysb* rdbuf() const; // возвращает указатель на буфер потока
_Mysb* rdbuf(_Mysb* _Strbuf) // заменяет буфер потока на новый и возвращает указатель на старый


C>То есть в первой строке мы устанавливаем буфер для clog буфер от log, точнее перенаправляем.


Точно.

C>Но вот я ни как не могу понять что значит original_clog_buffer();

C>В MSDN накопал похожий код, только вот такой
C>
C>streambuf* original_clog_buffer = clog.rdbuf(log.rdbuf());
C>

C>Как я понипаю разницы нет ни какой, то есть в нашем случае () равно =, то есть присваение.
C>Это так?

Для встроенных типов это всегда так.
Re[3]: Пару вопросов
От: size_t Россия  
Дата: 05.08.03 18:49
Оценка:
> А как выравнивание влияет на выполнение программы?
Чем правильнее, тем быстрее 8)
Это особенность процессора. Если он запрашивает n-байтное слово не выравненное на его n-байтную границу, то (при чтении из кэша) будет загружаться 2*n+1 тактов, по одному байту. Еще одна плохая вещь может произойти если переменная будет пересекать границу кэш линии... там еще куча тактов пройдет чтобы ее туда подгрузить. И это все так на наших X86 процессорах. На каком нить RISC посложнее это вообще приведет
Знаешь чем отличаются нормальные программы от кривых? Тем что в нормальных все выровнено, а не криво.
Posted via RSDN NNTP Server 1.7 beta
----------------
Нужное вписать.
Re[4]: Пару вопросов
От: Calc Россия  
Дата: 05.08.03 18:56
Оценка:
Здравствуйте, size_t, Вы писали:

>> А как выравнивание влияет на выполнение программы?

_>Чем правильнее, тем быстрее 8)
_>Это особенность процессора. Если он запрашивает n-байтное слово не выравненное на его n-байтную границу, то (при чтении из кэша) будет загружаться 2*n+1 тактов, по одному байту. Еще одна плохая вещь может произойти если переменная будет пересекать границу кэш линии... там еще куча тактов пройдет чтобы ее туда подгрузить. И это все так на наших X86 процессорах. На каком нить RISC посложнее это вообще приведет
_>Знаешь чем отличаются нормальные программы от кривых? Тем что в нормальных все выровнено, а не криво.

А что считать кривы? Когда выравнивание 4 или 1?
Или всё расчитывать надо?
Re[4]: Пару вопросов
От: Calc Россия  
Дата: 05.08.03 19:36
Оценка:
Здравствуйте, size_t, Вы писали:

_>Знаешь чем отличаются нормальные программы от кривых? Тем что в нормальных все выровнено, а не криво.


Возьмём мой класс:


#define PARAMS_COUNT 6

enum eparams { CounterUpdate, CounterNow, Segment, CUI, Log, Settings };

// структура в которой содержутся данные.
struct INISETTINGS
{
    LPTSTR pSection;
    LPTSTR pKey;
    int iNum;
};


class CSettings
{
    HINSTANCE m_hInst;

    // переменные файла настроек
    TCHAR szSettingsPath[MAX_PATH];            // путь к файлу настроек

    static INISETTINGS isParamsTable[PARAMS_COUNT];    // масив структур

    bool FillSettings();                // занести настройки в память
    void FillSettingsPath();            // определить путь к файлу настроек
    bool CreateSettingsFile();            // создать или открыть файл настроек

    static CSettings *s_Instance;
public:
    void Init();
    TCHAR szServerUpdate[MAX_PATH];
    bool bFirst;
    static CSettings *GetInstance()
    {
        if( NULL == s_Instance )
            s_Instance = new CSettings;
        return s_Instance;
    }
    int GetIntParam(int iElem);
    bool SetIntParam(int iParam, int iElem);    // занести параметр в память
    bool WriteParam(int iElem);            // записать элемент в файл, не нужно
    bool WriteAllParams();                // записать все параметры в файл
    int Main();                            // главная процедура, нафиг не нужна
};


Вот интересно узнать, что к чему пресовать.
А где можно почитать о выравнивании?
Ссылка, книга или ещё что нибудь.
Re[2]: Пару вопросов
От: e-Xecutor Россия  
Дата: 06.08.03 06:29
Оценка:
Здравствуйте, YVR, Вы писали:

YVR>Здравствуйте, Calc, Вы писали:


C>>1) Для чего это надо и какую пользу это даёт

C>>
C>>#pragma pack (push, 1)
C>>#pragma pack (pop)
C>>


YVR>Определяет выравнивание элементов структур

YVR>Например

YVR>
YVR>#pragma pack (push, 1) // сохранить текущее; установить выравнивание 1 байт
YVR>struct aaa {
YVR> char m1, m2;
YVR>}; // sizeof(aaa) == 2
YVR>#pragma pack (pop) // восстановить сохраненное

YVR>#pragma pack (push, 4) // сейчас обычно такое умолчание
YVR>struct bbb {
YVR> char m1, m2;
YVR>}; // sizeof(bbb) == 8
YVR>#pragma pack (pop)
YVR>


Вообще-то в последнем случае тоже будет 2.

а вот если так:
struct bbb{
  int a;
  char x;
};


то таки да, будет 8.


А вообще обычно отключение выравнивания нужно если
ты собираешься, например, вычитывать эту структуру из
файла или сетки.

Или передавать массив структур во "чужую" библиотеку.
В этом случае обычно бывает какая-то договорённость
на выравнивание.
Re[3]: Пару вопросов
От: YVR  
Дата: 06.08.03 07:33
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

YVR>>
YVR>>#pragma pack (push, 4) // сейчас обычно такое умолчание
YVR>>struct bbb {
YVR>> char m1, m2;
YVR>>}; // sizeof(bbb) == 8
YVR>>#pragma pack (pop)
YVR>>


EX>Вообще-то в последнем случае тоже будет 2.


Согласен. Грубо ошибся

EX>А вообще обычно отключение выравнивания нужно если

EX>ты собираешься, например, вычитывать эту структуру из
EX>файла или сетки.

EX>Или передавать массив структур во "чужую" библиотеку.

EX>В этом случае обычно бывает какая-то договорённость
EX>на выравнивание.

... или в память по-больше напихать (пусть и за счет некоторой потери производительности).
Re[5]: Пару вопросов
От: size_t Россия  
Дата: 06.08.03 09:14
Оценка:
>_>Знаешь чем отличаются нормальные программы от кривых? Тем что в нормальных все выровнено, а не криво.

>Возьмём мой класс:


>Вот интересно узнать, что к чему пресовать.

>А где можно почитать о выравнивании?
>Ссылка, книга или ещё что нибудь.

Там у тебя нечего прессовать. Все переменные по 4 байта (если для win32, а не win64).
Ставишь упаковку по 4 байта (она вроде как по дефолту стоит). Если бы были какие нить переменные типа char, short int и так далее, тогда можно было бы посжимать чего нить.
Вообще — хорошее правило для быстродействия — чтобы выравнивание не страдало надо упаковывать класс по максимальной длине элементарных переменных (элементарные, это то чем оперирует процессор, байты, инты, чары, флоуты, даблы, указатели и иже с ними).

На практике такое требуется только когда работаешь с предопределенными стандартами (например в структуре должны быть подряд упакованы char (1b), short int (2b), float(4b), char(1b) то без указаний для выравнивания — не жить); когда в классе только хранятся данные (редкий случай), а не используются для чтения; ну и все...

Вообще, при программировании под 32(64) разрядную среду упаковку надо ставить не менее 4(8) а то это тоже может привести к потерям скорости или неработоспособности (для супер навороченных risc систем).

Не самая необходимая в жизни штука.
Posted via RSDN NNTP Server 1.6
----------------
Нужное вписать.
Re[6]: Пару вопросов
От: MaximE Великобритания  
Дата: 06.08.03 09:26
Оценка: +1
Здравствуйте, size_t, Вы писали:

_>Ставишь упаковку по 4 байта (она вроде как по дефолту стоит)...


В vc по-умолчанию 8.
Re[6]: Пару вопросов
От: Calc Россия  
Дата: 06.08.03 09:48
Оценка:
Здравствуйте, size_t, Вы писали:

_>например в структуре должны быть подряд упакованы char (1b), short int (2b), float(4b), char(1b) то без указаний для выравнивания — не жить


А тут какое выравнивание делать?
1 или по величине самого большого члена?
Re[7]: Пару вопросов
От: size_t Россия  
Дата: 06.08.03 10:29
Оценка:
> _>например в структуре должны быть подряд упакованы char (1b), short int (2b), float(4b), char(1b) то без указаний для выравнивания — не жить
>
> А тут какое выравнивание делать?
> 1 или по величине самого большого члена?

В данном случае надо 1, но это приведет к потерям скорости если начать записывать в тот самый int или float. Чтобы этих потерь небыло надо поставить 4, но (!) тогда распределение их в памяти изменится, что приведет к несовместимости с некой спецификацией, которая требовала именно такого расположения данных
Posted via RSDN NNTP Server 1.6
----------------
Нужное вписать.
Re[8]: Пару вопросов
От: Calc Россия  
Дата: 06.08.03 10:33
Оценка:
Здравствуйте, size_t, Вы писали:

>> _>например в структуре должны быть подряд упакованы char (1b), short int (2b), float(4b), char(1b) то без указаний для выравнивания — не жить

>>
>> А тут какое выравнивание делать?
>> 1 или по величине самого большого члена?

_>В данном случае надо 1, но это приведет к потерям скорости если начать записывать в тот самый int или float. Чтобы этих потерь небыло надо поставить 4, но (!) тогда распределение их в памяти изменится, что приведет к несовместимости с некой спецификацией, которая требовала именно такого расположения данных


А как дела обстоят с объединениями (union) ?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.