ساختار در زبان MQL5 – بخش 2


در مقالهی پیشین یعنی چهارمین مقاله آموزش زبان mql از سری مقالات مرتبط با برنامهنویسی در بازارهای مالی به شرح و بررسی «ساختار در زبان MQL5» پرداختیم. در پنجمین مقالهی این سری نیز به تکمیل و جمعبندی این موضوع میپردازیم.
– – –

“pack” برای تراز کردن ساختار و فیلدهای کلاس #
در این بخش از آموزش زبان mql در ادامه و تکمیل بخش قبل به بررسی ساختار در زبان MQL5 میپردازیم. در بررسی ساختار در زبان MQL5 یک از نکات حائز اهمیت توجه به بحث Alignment ساختار است. ویژگی(attribute) pack، امکان تنظیم تراز فیلدهای ساختار یا کلاس را فراهم میکند.
pack([n])
که در آن n یکی از مقادیر زیر است: 1، 2، 4، 8 یا 16. و یا ممکن است وجود نداشته باشد.
struct pack(sizeof(long)) MyStruct { // structure members are to be aligned to the 8-byte boundary }; or struct MyStruct pack(sizeof(long)) { // structure members are to be aligned to the 8-byte boundary };

‘pack(1)’ به طور پیش فرض برای ساختارها اعمال میشود. به این معنی که اعضای ساختار یکی پس از دیگری در حافظه قرار میگیرند و اندازه ساختار برابر است با مجموع اندازه اعضای آن.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- simple structure with no alignment struct Simple_Structure { char c; // sizeof(char)=1 short s; // sizeof(short)=2 int i; // sizeof(int)=4 double d; // sizeof(double)=8 }; //--- declare a simple structure instance Simple_Structure s; //--- display the size of each structure member Print("sizeof(s.c)=",sizeof(s.c)); Print("sizeof(s.s)=",sizeof(s.s)); Print("sizeof(s.i)=",sizeof(s.i)); Print("sizeof(s.d)=",sizeof(s.d)); //--- make sure the size of POD structure is equal to the sum of its members' size Print("sizeof(simple_structure)=",sizeof(Simple_Structure)); /* Result: sizeof(s.c)=1 sizeof(s.s)=2 sizeof(s.i)=4 sizeof(s.d)=8 sizeof(Simple_Structure )=15 */ }
تراز کردن فیلدهای ساختار ممکن است در هنگام تبادل داده با کتابخانههای شخص ثالث (*.DLL) که چنین Alignment ای اعمال میشود، مورد نیاز باشد.
ساختار در زبان MQL5 و نحوه عملکرد تراز(Alignment)
بیایید از چند مثال برای نشان دادن نحوه عملکرد تراز استفاده کنیم. ما ساختاری متشکل از چهار عضو بدون تراز را اعمال خواهیم کرد.
//--- simple structure with no alignment struct Simple_Structure pack() // no size is specified, alignment to the boundary of 1 byte is to be set { char c; // sizeof(char)=1 short s; // sizeof(short)=2 int i; // sizeof(int)=4 double d; // sizeof(double)=8 }; //--- declare a simple structure instance Simple_Structure s;
فیلدهای ساختار باید یکی پس از دیگری با توجه به ترتیب تعریف و اندازه نوع در حافظه قرار گیرند. اندازه ساختار 15 است، در حالی که افست فیلدهای ساختار در آرایهها تعریف نشده است.

حالا همان ساختار را با تراز 4 بایت تعریف کرده و کد را اجرا کنید.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- simple structure with the 4-byte alignment struct Simple_Structure pack(4) { char c; // sizeof(char)=1 short s; // sizeof(short)=2 int i; // sizeof(int)=4 double d; // sizeof(double)=8 }; //--- declare a simple structure instance Simple_Structure s; //--- display the size of each structure member Print("sizeof(s.c)=",sizeof(s.c)); Print("sizeof(s.s)=",sizeof(s.s)); Print("sizeof(s.i)=",sizeof(s.i)); Print("sizeof(s.d)=",sizeof(s.d)); //--- make sure the size of POD structure is now not equal to the sum of its members' size Print("sizeof(Simple_Structure)=",sizeof(Simple_Structure)); /* Result: sizeof(s.c)=1 sizeof(s.s)=2 sizeof(s.i)=4 sizeof(s.d)=8 sizeof(Simple_Structure)=16 // structure size has changed */ }
اندازه ساختار تغییر کرده است به طوری که تمام اعضای 4 بایت و بیشتر دارای یک افست از ابتدای ساختار مضرب 4 بایت هستند. اعضای کوچکتر باید با مرز اندازه خودشان تراز شوند (مثلاً 2 برای «short»). اینگونه به نظر می رسد (بایت اضافه شده به رنگ خاکستری نشان داده شده است).

در این حالت، 1 بایت بعد از عضو s.c اضافه می شود، به طوری که فیلد s.s (sizeof(short)==2) دارای مرز 2 بایت است (تراز برای نوع ‘short’).
افست ابتدای ساختار در آرایه نیز با مرز 4 بایت تراز میشود، یعنی آدرسهای عناصر a[0]، a[1] و a[n] برای Simple_Structure باید مضرب 4 بایت باشند. []arr.
بیایید دو ساختار دیگر متشکل از انواع مشابه با تراز 4 بایتی اما ترتیب اعضای متفاوت را در نظر بگیریم. در ساختار اول، اعضا به ترتیب اندازه نوع صعودی قرار گرفتهاند.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- simple structure aligned to the 4-byte boundary struct CharShortInt pack(4) { char c; // sizeof(char)=1 short s; // sizeof(short)=2 int i; // sizeof(double)=4 }; //--- declare a simple structure instance CharShortInt ch_sh_in; //--- display the size of each structure member Print("sizeof(ch_sh_in.c)=",sizeof(ch_sh_in.c)); Print("sizeof(ch_sh_in.s)=",sizeof(ch_sh_in.s)); Print("sizeof(ch_sh_in.i)=",sizeof(ch_sh_in.i)); //--- make sure the size of POD structure is equal to the sum of its members' size Print("sizeof(CharShortInt)=",sizeof(CharShortInt)); /* Result: sizeof(ch_sh_in.c)=1 sizeof(ch_sh_in.s)=2 sizeof(ch_sh_in.i)=4 sizeof(CharShortInt)=8 */ }
همانطور که میبینیم، اندازه ساختار 8 است و از دو بلوک 4 بایتی تشکیل شده است. بلوک اول شامل فیلدهایی با انواع ‘char’ و ‘short’ است، در حالی که بلوک دوم حاوی فیلدهایی با نوع ‘int’ است.

حالا بیایید با حرکت دادن عضو نوع ‘short’ به انتها، ساختار اول را به ساختار دوم تبدیل کنیم، که فقط در ترتیب فیلد متفاوت است.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- simple structure aligned to the 4-byte boundary struct CharIntShort pack(4) { char c; // sizeof(char)=1 int i; // sizeof(double)=4 short s; // sizeof(short)=2 }; //--- declare a simple structure instance CharIntShort ch_in_sh; //--- display the size of each structure member Print("sizeof(ch_in_sh.c)=",sizeof(ch_in_sh.c)); Print("sizeof(ch_in_sh.i)=",sizeof(ch_in_sh.i)); Print("sizeof(ch_in_sh.s)=",sizeof(ch_in_sh.s)); //--- make sure the size of POD structure is equal to the sum of its members' size Print("sizeof(CharIntShort)=",sizeof(CharIntShort)); /* Result: sizeof(ch_in_sh.c)=1 sizeof(ch_in_sh.i)=4 sizeof(ch_in_sh.s)=2 sizeof(CharIntShort)=12 */ }
اگرچه محتوای ساختار تغییر نکرده است، تغییر توالی اعضا باعث افزایش اندازه آن شده است.

تراز(Alignment) در وراثت
در هنگام وراثت باید تراز را در نظر گرفت. بیایید این را با استفاده از ساختار Parent ساده که دارای یک عضو از نوع “char” است نشان دهیم. اندازه ساختار(structure) بدون تراز 1 است.
struct Parent { char c; // sizeof(char)=1 };
بیایید کلاس فرزند Children را ایجاد کنیم که دارای عضو نوع short’ (sizeof(short)=2)’ است.
struct Children pack(2) : Parent { short s; // sizeof(short)=2 };
در نتیجه، هنگام تنظیم alignment روی 2 بایت، اندازه ساختار برابر با 4 است، اگرچه اندازه اعضای آن 3 است. در این مثال، 2 بایت باید به کلاس Parent اختصاص داده شود، به طوری که دسترسی به فیلد ‘short’ کلاس فرزند به 2 بایت تراز شده است.
دانش نحوه تخصیص حافظه برای اعضای ساختار ضروری است اگر یک برنامه MQL5 با داده های شخص ثالث با نوشتن/خواندن در سطح فایل ها یا جریان ها تعامل داشته باشد.
فهرست MQL5\Include\WinAPI کتابخانه استاندارد شامل توابع کار با توابع WinAPI است. این توابع ساختارها را با یک تراز مشخص برای مواردی که برای کار با WinAPI مورد نیاز است اعمال می کنند.
offsetof یک فرمان ویژه است که مستقیماً با ویژگی pack مرتبط است. این به ما امکان میدهد از ابتدای ساختار یک افست عضو را بدست آوریم.
//--- declare the Children type variable Children child; //--- detect offsets from the beginning of the structure Print("offsetof(Children,c)=",offsetof(Children,c)); Print("offsetof(Children,s)=",offsetof(Children,s)); /* Result: offsetof(Children,c)=0 offsetof(Children,s)=2 */
‘Specifier ‘final #
استفاده از مشخص کننده “final” در طی تعریف ساختار، ارث بردن بیشتر از این ساختار را ممنوع میکند. اگر ساختاری نیازی به تغییرات بیشتر نداشته باشد، یا تغییراتی به دلایل امنیتی مجاز نباشد، این ساختار را با اصلاح کننده “final” تعریف کنید. علاوه بر این، تمام اعضای ساختار نیز به طور ضمنی نهایی تلقی خواهند شد.
struct settings final { //--- Structure body }; struct trade_settings : public settings { //--- Structure body };
- اگر همانطور که در مثال بالا نشان داده شده است سعی کنید از ساختاری با اصلاح کننده ‘final‘ ارثبری کنید، کامپایلر یک خطا را برمیگرداند :
cannot inherit from 'settings' as it has been declared as 'final' see declaration of 'settings'
در مقالات بعدی آموزش ام کیو ال، مطالب آموزش ساختار در زبان MQL پی گرفته و سایر نکات مربوط به این بخش را شرح خواهیم داد.
همچنین میتوانید از سسله مقالات آموزش Python سایت جهان بورس استفاده نمایید.
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.