سؤال

على سبيل المثال، إذا قمت بتعريف متغير طويل، فهل يمكنني أن أفترض أنه سيتم محاذاته دائمًا على حدود "sizeof(long)"؟تقول تعليمات Microsoft Visual C++ عبر الإنترنت ذلك، ولكن هل هذا سلوك قياسي؟

بعض المعلومات الإضافية:

أ.من الممكن إنشاء عدد صحيح غير محاذٍ بشكل صريح (*bar):

شار فو[5]

int * bar = (int *)(&foo[1]);

ب.من الواضح أن #pragma pack() يؤثر فقط على الهياكل والفئات والاتحادات.

ج.تنص وثائق MSVC على أن أنواع POD تتماشى مع أحجامها الخاصة (ولكن هل هذا دائمًا أم افتراضيًا، وهل هو سلوك قياسي، لا أعرف)

هل كانت مفيدة؟

المحلول

كما ذكر آخرون، هذا ليس جزءًا من المعيار ويترك للمترجم لتنفيذه كما يراه مناسبًا للمعالج المعني.على سبيل المثال، يمكن لـ VC تنفيذ متطلبات محاذاة مختلفة لمعالج ARM بسهولة مقارنة بمعالجات x86.

ينفذ Microsoft VC ما يسمى أساسًا بالمحاذاة الطبيعية حتى الحجم المحدد بواسطة توجيه حزمة #pragma أو خيار سطر الأوامر /Zp.وهذا يعني أنه، على سبيل المثال، سيتم محاذاة أي نوع POD بحجم أصغر أو يساوي 8 بايت بناءً على حجمه.سيتم محاذاة أي شيء أكبر على حدود 8 بايت.

إذا كان من المهم أن تتحكم في محاذاة المعالجات المختلفة والمترجمين المختلفين، فيمكنك استخدام حجم التعبئة 1 وحشو الهياكل الخاصة بك.

#pragma pack(push)
#pragma pack(1)    
struct Example
{
   short data1;     // offset 0
   short padding1;  // offset 2
   long data2;      // offset 4
};
#pragma pack(pop)

في هذا الكود، padding1 المتغير موجود فقط للتأكد من محاذاة data2 بشكل طبيعي.

الإجابة على أ:

نعم، يمكن أن يتسبب ذلك بسهولة في محاذاة البيانات بشكل غير صحيح.على معالج x86، لا يضر هذا كثيرًا على الإطلاق.في المعالجات الأخرى، قد يؤدي ذلك إلى حدوث عطل أو تنفيذ بطيء جدًا.على سبيل المثال، قد يطرح معالج Alpha استثناءً للمعالج والذي سيتم اكتشافه بواسطة نظام التشغيل.سيقوم نظام التشغيل بعد ذلك بفحص التعليمات ثم القيام بالعمل المطلوب للتعامل مع البيانات غير المحاذاة.ثم يستمر التنفيذ.ال __unaligned يمكن استخدام الكلمة الأساسية في VC لتحديد الوصول غير المحاذاة للبرامج غير x86 (أي.قوة).

نصائح أخرى

بشكل افتراضي، نعم.ومع ذلك، يمكن تغييره عبر الحزمة () #pragma.

لا أعتقد أن معيار C++ يضع أي متطلبات في هذا الصدد، ويترك الأمر للتنفيذ.

لا يتطلب C وC++ أي نوع من المحاذاة.لكن المحاذاة الطبيعية مفضلة بشدة بواسطة x86 وهي كذلك مطلوب بواسطة معظم بنيات وحدة المعالجة المركزية الأخرى، ويبذل المترجمون عمومًا قصارى جهدهم لإبقاء وحدات المعالجة المركزية سعيدة.لذا، من الناحية العملية، لن ترى أن المترجم يقوم بإنشاء بيانات غير محاذاة إلا إذا قمت بتحريف ذراعه حقًا.

نعم، تتم محاذاة كافة الأنواع دائمًا على الأقل وفقًا لمتطلبات المحاذاة الخاصة بها.

كيف يمكن أن يكون خلاف ذلك؟

لكن لاحظ أن حجم النوع () ليس هو نفسه محاذاته.

يمكنك استخدام الماكرو التالي لتحديد متطلبات المحاذاة للنوع:

#define ALIGNMENT_OF( t ) offsetof( struct { char x; t test; }, test )

يعتمد على المترجم والبراغمات ومستوى التحسين.باستخدام المترجمين الحديثين، يمكنك أيضًا اختيار تحسين الوقت أو المساحة، مما قد يؤدي إلى تغيير محاذاة الأنواع أيضًا.

بشكل عام سيكون السبب في ذلك هو أن القراءة/الكتابة إليه تكون أسرع بهذه الطريقة.لكن كل مترجم تقريبًا لديه مفتاح لإيقاف تشغيله.في دول مجلس التعاون الخليجي لها -خبيثة-؟؟؟.مع المجاميع يتم محاذاة وحجمها بشكل عام بناءً على متطلبات المحاذاة لكل عنصر بداخلها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top