Ошибки, баги, вопросы - страница 2499

 
fxsaber:

Хочется разобраться.

выравнивание данных это не 

Print(sizeof(A)); // 2

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

выравнивание это расположение данных в физической памяти, как и написано в справке " для передачи в импортированные dll-функции" - в различных компиляторах и в языках типы данных могут отличаться по своим размерам или вернее по способу хранения в памяти, вот и нужно использовать struct A pack(4) чтобы каждый член структуры "не вылез за свою клеточку" - байты 

вот как на хабре в статье:

struct Foo
{
    char ch;
    int value;
};

1 байт: ch

2 байт: пусто

3 байт: пусто                                        ЭТО  char ch;  

4 байт: пусто


5 байт: value[0]

6 байт: value[1]                                   ЭТО   int value;     

7 байт: value[2]

8 байт: value[3]


 
Igor Makanu:

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

Это не так

struct A pack(4)
{
  short j;
  char i;
};

void OnStart()
{
  Print(sizeof(A)); // 4
}
 
fxsaber:

Это не так

тогда Ваш пример проверил что sizeof() корректно посчитал "вес" структуры в байтах,

остается только физическую память проверить, но по моему будет только при вызове dll работать, не факт что разработчики не заоптимизировали хранение данных в памяти ;) - т.е. если не используется pack(4) по назначению в коде, то может он быть и проигнорирован в исполняемом коде

 
Igor Makanu:

тогда Ваш пример проверил что sizeof() корректно посчитал "вес" структуры в байтах

Поэтому и возникает вопрос, как на самом деле работает выравнивание? Документация и Хабр своими примерами не раскрыли алгоритм.

Igor Makanu:

остается только физическую память проверить, но по моему будет только при вызове dll работать, не факт что разработчики не заоптимизировали хранение данных в памяти ;) - т.е. если не используется pack(4) по назначению в коде, то может он быть и проигнорирован в исполняемом коде

В физической памяти аналогично.
struct A pack(4)
{
  short j;
  char i;
};

void OnStart()
{
  Print(sizeof(A)); // 4
  
  const int handle = FileOpen(__FILE__, FILE_WRITE | FILE_BIN);
  
  if (handle != INVALID_HANDLE)
  {
    A a = {0};
    
    FileWriteStruct(handle, a);
    Print(FileTell(handle)); // 4
    
    FileClose(handle);
  }
}
 
fxsaber:

Поэтому и возникает вопрос, как на самом деле работает выравнивание? Документация и Хабр своими примерами не раскрыли алгоритм.

от конкретного компилятора все зависит, наверное можно в MQL попробовать в union посмотреть как данные были сохранены при использовании  pack(4)

 
Igor Makanu:

от конкретного компилятора все зависит, наверное можно в MQL попробовать в union посмотреть как данные были сохранены при использовании  pack(4)

Для этого есть offsetof и другие способы.


ЗЫ Получается, что задание выравнивания служит для придания однозначности. Но не для собственного использования. Ну и хорошо видно, что от порядка полей зависит потребление памяти и, видимо, производительность.

 
fxsaber:

ЗЫ Получается, что задание выравнивания служит для придания однозначности. Но не для собственного использования.

а это и есть "от конкретного компилятора все зависит" - разработчики часто идут на ухищрения для поднятия производительности своих разработок относительно других, в MQL отсутствуют директивы компилятора - типа отключить оптимизацию исходного кода и т.п. - нельзя увидеть разницу в работе или использовании ОЗУ нативного  кода


ЗЫ: я не уверен, что пример с записью в файл однозначно всегда корректно работает, кто то недавно писал, что MQL используется Win API при записи в файл, тут может быть для совместимости с API функциями некоторые допущения быть произведены - но это мои догадки, не являюсь разработчиком компиляторов (((

 
fxsaber:

Для этого есть offsetof и другие способы.


ЗЫ Получается, что задание выравнивания служит для придания однозначности. Но не для собственного использования. Ну и хорошо видно, что от порядка полей зависит потребление памяти.

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

 
Vict:

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

Стало ясно, всем спасибо.

 
fxsaber:

Хочется разобраться.

А что тут разбираться если в документации чётко написано

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

#pragma pack(1)

И дальше по тексту...

То-есть выравнивание в MQL5 отсутствует вообще.

Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
  • www.mql5.com
Структура является набором элементов произвольного типа (кроме типа void). Таким образом, структура объединяет логически связанные данные разных типов. Объявление структуры Имя структуры нельзя использовать в качестве идентификатора (имени переменной или функции). Следует иметь ввиду, что в MQL5 элементы структуры следуют непосредственно друг...
Причина обращения: