ما هو الفرق بين المتغير العالمي الثابت والمتغير الثابت؟

StackOverflow https://stackoverflow.com/questions/346306

سؤال

لقد استخدمت متغيرًا عامًا ثابتًا ومتغيرًا ثابتًا متقلبًا في نطاق الملف،

يتم تحديث كلاهما بواسطة ISR وتتحقق الحلقة الرئيسية والحلقة الرئيسية من قيمة المتغير.

هنا أثناء التحسين لم يتم تحسين المتغير العام ولا المتغير المتقلب.لذلك بدلاً من استخدام متغير متقلب، يحل المتغير العام المشكلة.

فهل من الجيد استخدام المتغير العام بدلاً من المتغير؟

أي سبب محدد لاستخدام ثابت متقلب؟؟

أي برنامج مثال سيكون موضع تقدير.

شكرا لك مقدما..

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

المحلول

إنها أشياء مختلفة.أنا لست خبيرا في الدلالات المتقلبة.لكنني أعتقد أنه من المنطقي ما هو موضح هنا.

عالمي

عالمي يعني فقط أنه تم الإعلان عن المعرف المعني في نطاق الملف.هناك نطاقات مختلفة، تسمى الوظيفة (حيث يتم تعريف تسميات goto)، والملف (حيث توجد العناصر العالمية)، والكتلة (حيث توجد المتغيرات المحلية العادية)، والنموذج الأولي للوظيفة (حيث توجد معلمات الوظيفة).هذا المفهوم موجود فقط لتنظيم رؤية المعرفات.ليس لها أي علاقة بالتحسينات.

ثابتة

static هي مدة تخزين (لن ننظر إلى ذلك هنا) وطريقة لإعطاء اسم مُعلن ضمن الارتباط الداخلي لنطاق الملف.يمكن القيام بذلك للوظائف أو الكائنات المطلوبة فقط ضمن وحدة ترجمة واحدة.قد يكون المثال النموذجي أ help تقوم الدالة بطباعة المعلمات المقبولة، والتي يتم استدعاؤها فقط من ملف main وظيفة محددة في نفسه .c ملف.

6.2.2/2 في مسودة C99:

إذا كان إعلان تحديد نطاق نطاق لكائن أو دالة يحتوي على ساكنة فئة التخزين ، فإن المعرف له صلة داخلية.

الارتباط الداخلي يعني أن المعرف غير مرئي خارج وحدة الترجمة الحالية (مثل help وظيفة أعلاه).

متقلب

المتقلب شيء مختلف:(6.7.3/6)

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

يوفر المعيار مثالاً ممتازًا لمثال حيث volatile سيكون زائدا عن الحاجة (5.1.2.3/8):

قد يحدد التنفيذ مراسلات فردية بين الدلالات التجريدية والفعلية:في كل نقطة تسلسل ، ستوافق قيم الكائنات الفعلية مع تلك التي تحددها الدلالات التجريدية.الكلمة الرئيسية volatileسيكون بعد ذلك زائدة عن الحاجة.

نقاط التسلسل هي النقاط التي يكون فيها تأثير الآثار الجانبية المتعلقة آلة مجردة مكتملة (أي لم يتم تضمين الظروف الخارجية مثل قيم خلايا الذاكرة).بين اليمين واليسار && و ||, ، بعد ; والعودة من استدعاء دالة هي نقاط تسلسل على سبيل المثال.

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

للحصول على نظرة عامة سهلة الفهم، لدى شركة Intel مقالة رائعة حول هذا الموضوع هنا.

ماذا يجب ان افعل الان؟

استمر في الإعلان عن أن بيانات نطاق الملف (العالمي) الخاصة بك متقلبة.البيانات الشاملة في حد ذاتها لا تعني أن قيمة المتغيرات ستساوي القيمة المخزنة في الذاكرة.والثابت لا يجعل كائناتك محلية إلا لوحدة الترجمة الحالية (current .c الملفات وجميع الملفات الأخرى #المتضمنة بها).

نصائح أخرى

اسمحوا لي أولاً أن أذكر أن المتغير العام الثابت هو نفس المتغير العام، باستثناء أنك تقصر المتغير على نطاق الملف.أي.لا يمكنك استخدام هذا المتغير العام في ملفات أخرى عبر ملف extern الكلمة الرئيسية.

لذا يمكنك تقليل سؤالك إلى المتغيرات العالمية مقابل المتغيرات المتقلبة.

الآن على المتقلبة:

يحب const, volatile هو معدل النوع.

ال volatile تم إنشاء الكلمة الأساسية لمنع تحسينات برنامج التحويل البرمجي التي قد تجعل التعليمات البرمجية غير صحيحة، خاصة عند وجود أحداث غير متزامنة.

الكائنات المعلنة على أنها volatile لا يجوز استخدامها في بعض التحسينات.

يقرأ النظام دائمًا القيمة الحقيقية الحالية للكائن المتطاير عند النقطة التي يتم استخدامه فيها، حتى لو طلبت تعليمات سابقة قيمة من نفس الكائن.كما يتم كتابة قيمة الكائن فورًا عند التعيين.وهذا يعني أنه لا يوجد تخزين مؤقت للمتغير المتقلب في سجل وحدة المعالجة المركزية.

دكتور.لدى Jobb's مقالة رائعة عن المواد المتقلبة.

وهنا مثال من د.مقالة أيوب:

class Gadget
{
public:
    void Wait()
    {
        while (!flag_)
        {
            Sleep(1000); // sleeps for 1000 milliseconds
        }
    }
    void Wakeup()
    {
        flag_ = true;
    }
    ...
private:
    bool flag_;
};

إذا رأى المترجم ذلك Sleep() هي مكالمة خارجية، وسوف نفترض ذلك Sleep() لا يمكن تغيير قيمة flag_ المتغير.لذلك قد يقوم المترجم بتخزين قيمة flag_ في السجل.وفي هذه الحالة، لن يتغير أبدًا.ولكن إذا قام مؤشر ترابط آخر باستدعاء تنبيه، فإن مؤشر الترابط الأول لا يزال يقرأ من سجل وحدة المعالجة المركزية. Wait() لن يستيقظ أبدا.

فلماذا لا يتم تخزين المتغيرات مؤقتًا في السجلات وتجنب المشكلة تمامًا؟اتضح أن هذا التحسين يمكن أن يوفر لك الكثير من الوقت بشكل عام.لذلك يسمح لك C/C++ بتعطيله بشكل صريح عبر ملف volatile الكلمة الرئيسية.

الحقيقة فوق ذلك flag_ كان متغيرا عضوا، وليس متغيرا عاما (ولا العمومي ثابت) لا يهم.يعطي الشرح التالي للمثال المنطق الصحيح حتى إذا كنت تتعامل مع المتغيرات العامة (والمتغيرات العامة الثابتة).

من المفاهيم الخاطئة الشائعة أن الإعلان عن متغير volatile يكفي لضمان سلامة الخيط.العمليات على المتغير لا تزال غير ذرية، على الرغم من أنها لم يتم "تخزينها مؤقتًا" في السجلات

متقلبة مع المؤشرات:

متقلب مع المؤشرات، ويعمل مثل const مع المؤشرات.

متغير من النوع volatile int * يعني أن المتغير الذي يشير إليه المؤشر متقلب.

متغير من النوع int * volatile يعني أن المؤشر نفسه متقلب.

وو"متقلبة" الكلمة تشير المترجم عدم القيام ببعض التحسينات على كود تنطوي على هذا المتغير. إذا كنت تستخدم فقط متغير عمومي، لا شيء يمنع مترجم إلى خطأ تحسين التعليمات البرمجية.

مثال:

#define MYPORT 0xDEADB33F

volatile char *portptr = (char*)MYPORT;
*portptr = 'A';
*portptr = 'B';

وبدون "متقلبة"، الكتابة الأولى قد يكون الأمثل للخروج.

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

متغير متقلب على ويكيبيديا

قد لا تكون مختلفة في بيئتك الحالية، لكن التغييرات الطفيفة قد تؤثر على السلوك.

  • أجهزة مختلفة (المزيد من المعالجات، بنية ذاكرة مختلفة)
  • نسخة جديدة من المترجم مع تحسين أفضل.
  • اختلاف عشوائي في التوقيت بين المواضيع.قد تحدث المشكلة مرة واحدة فقط في كل 10 ملايين.
  • إعدادات تحسين المترجم المختلفة.

يعد استخدام بنيات تعدد العمليات المناسبة من البداية أكثر أمانًا على المدى الطويل، حتى لو بدت الأمور وكأنها تعمل في الوقت الحالي بدونها.

بالطبع، إذا لم يكن برنامجك متعدد الخيوط فلا يهم.

وأنا الجواب +1 friol ل. وأود أن أضيف بعض توضيحات كما يبدو أن هناك الكثير من الالتباس في إجابات مختلفة: في C تقلبا ليس جاوة متقلبة

وهكذا أولا، يمكن أن المجمعين القيام بالكثير من التحسينات على على أساس تدفق البيانات من البرنامج، متقلبة في C يمنع ذلك، فإنه يجعل متأكد من أنك حقا تحميل / مخزن إلى الموقع في كل مرة (بدلا من استخدام سجلات القضاء عليه من مثل). ومن المفيد عندما يكون لديك ذاكرة تعيين ميناء IO، كما أشارت في friol بها.

ومتقلبا في C ليس لديها ما تفعله مع مخابئ الأجهزة أو خاصية تعدد. لم تقم بإدخال الأسوار الذاكرة، ولديك اي garanty على ترتيب العمليات إذا كان اثنان المواضيع تفعل يصل إليها. الكلمة المتقلبة جاوة يفعل بالضبط أنه على الرغم من: إدخال الأسوار الذاكرة عند الحاجة

المتغير المتقلب يعني أن القيمة المخصصة له ليست ثابتة، أي إذا كانت دالة تحتوي على متغير متطاير "a=10" وكانت الدالة تضيف 1 في كل استدعاء لتلك الدالة، فإنها سترجع دائمًا قيمة محدثة.{ volatile int a=10; a++; }عندما يتم استدعاء الدالة المذكورة أعلاه مرارا وتكرارا، فلن تتم إعادة تهيئة المتغير a إلى 10، وسوف يظهر دائما القيمة المحدثة حتى يتم تشغيل البرنامج.الإخراج الأول = 10 ثم 11 ثم 12 وهلم جرا.

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