لماذا بعض المتغيرات CONT التي تشير إلى بعض المتغيرات CONTS المصدرة احصل على القيمة 0؟

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

سؤال

النظر في ما يلي. لدي ثوابتان مصدران على النحو التالي:

// somefile.h
extern const double cMyConstDouble;
extern const double cMyConstDouble2;

و

// somefile.cpp
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

يشار الآن الثوابت إلى بعض مكان آخر لتحديد ثوابتين ثابتين (مرئي محلي):

// someotherfile.cpp
#include "somefile.h"
static const double cAnotherDouble = 1.1*cMyConstDouble;
static const double cAnotherDouble2 = 1.1*cMyConstDouble2;
printf("cAnotherDouble = %g, cAnotherDouble2 = %g\n",
       cAnotherDouble, cAnotherDouble2);

التي تسلم الناتج التالي:

cAnotherDouble = 3.454, cAnotherDouble2 = 0

لماذا هو الثاني مزدوج 0؟ أنا أستخدم .NET 2003 C ++ مترجم (13.10.3077).

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

المحلول

نظرا لأن CMYCONSTBLEBLE تم الإعلان عنها على أنها خارجية، فإن التحويل البرمجي غير قادر على تحمل قيمته ولا تولد تهيئة وقت الترجمة ل cmyconstduble2. نظرا لأن CMYCONSTDDOBLE2 لا يترجم وقتا تجميع الوقت، فإن ترتيب التهيئة بالنسبة للموثر الثاني هو عشوائي (غير محدد). يرى التهيئة الثابتة الفشل للمزيد من المعلومات.

نصائح أخرى

لن أغرق إصبع قدمي في مشكلات خارجية هنا، ولكن لماذا ببساطة لا تضع Consts في ملفات الرأس المناسبة ونسيان "تصدير" استخدامها خارجيا؟ هذه هي الطريقة التي يفترض استخدام consts بها في C ++، ولماذا لديهم ارتباط داخلي.

بعبارات أخرى:

// someheader.h
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

و #include هذا الملف أينما كنت في حاجة إليها.

هذا أمر خطير أن تفعله حيث يعتمد المتغير الثابت الخاص بك في ملف مصدر واحد على المتغير الثابت آخر في ملف CPP آخر. يفحص التهيئة الثابتة الفشل للمزيد من المعلومات.

إذا قمت بتغيير تهيئة cMyConstDouble2 لهذا هنا:

const double cMyConstDouble2 = 2.5*3.14;

ثم يجب أن يتصرف البرنامج صحيحا. السبب في ذلك هو أن المتغيرات التي

  • لديه نوع جراب
  • تتم تهيئتها مع تعبيرات ثابتة (1)

يتم تهيئة وقت التهيئة الثابتة. هذه التهيئة تشمل ذلك

  • تهيئة صفر الكل كائنات وجود مدة تخزين ثابت
  • تهيئة التهيئة من القرون مع تعبيرات ثابتة

من المتغيرات الموضحة الخاصة بك، فقط cMyConstDouble يرضي كلا الشرطين ليتم تهيئته بالكامل في وقت التهيئة الثابتة. ومع ذلك، cMyConstDouble2 لا، نظرا لعدم إرضاء متطلبات التعبير المستمر. على وجه الخصوص، يتضمن متغير لا يحتوي على نوع جزءا لا يتجزأ (هنا، له نوع نقطة عائمة). ومع ذلك، النقطة العائمة حرفي نكون يسمح في التعبيرات المستمر الحسابية. لذلك 2.5*3.14 هو تعبير ثابت حسابي. وهذا هو السبب في أن تغيير المهيئ إلى ذلك سيتطلب تهيئة قانونيا.


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

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
                // may be statically initialized to 0.0 or
                // dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0

إذا كان التهيئة الديناميكية لا يغير أي متغير تخزين ثابت آخر (راضي لك الرمز) وعندما ينتج التهيئة الثابتة نفس القيمة كما سيتم إنتاجها بواسطة التهيئة الديناميكية عندما تتم تهيئة جميع الكائنات غير المطلوبة إلى التهيئة القانونية بشكل ثابت ديناميكيا (راضي أيضا لك الرمز) - ثم يسمح للمتغير بالتهيئة بشكل ثابت. هذان الشرطين راضين أيضا في القانون أعلاه لكلا المتغيرين d2 و d1:

تحليل d2

  • = d1 لا يغير أي متغير تخزين ثابت آخر
  • عندما كلاهما d2 و d1 تتم تهيئة ديناميكيا، ثم d2 سيتم تهيئة ل 0.0, ، لأن d2 محددة قبل d1, ، والتهيئة الديناميكي لل d2 سوف الاستيلاء على قيمة d1 اعتبارا من الدولة بعد التهيئة الثابتة (حيث الصفر فقط تهيئة d1 يأخذ مكانا).

تحليل d1

  • = fd() لا يغير أي متغير تخزين ثابت آخر
  • عندما كلاهما d2 و d1 تتم تهيئة ديناميكيا، ثم = fd() سوف تهيئة d1 ل 1.0.

لذلك، قد يتم تهيئة المحول البرمجي d1 ثابت إلى 1.0, ، لأن كلا الشرطين لتهيئة التهيئة الثابتة الاختيارية.

  • إذا المحول البرمجي يقرر تهيئة d1 و d2 ديناميكيا، ثم d2 سيتم تهيئة ل 0.0, ، لأنه سوف يمسك قيمة d1 كما كان بعد تهيئة الصفر.

  • ومع ذلك, إذا المحول البرمجي يقرر تهيئة d1 ثابت و d2 ديناميكيا، ثم d2 سيتم تهيئة ل 1.0, ، منذ التهيئة الديناميكية لل d2 سوف الاستيلاء على القيمة الموحدة بالكامل لل d1 كما كان فقط بعد التهيئة الثابتة.

لست متأكدا مما قيمة d2 هو متى d1 و d2 يتم تهيئة ثابتة، رغم ذلك. وهذا هو، سواء d2 من المفترض أن يحصل على 0.0 أو ال 1.0, ، نظرا لعدم وجود أمر محدد لتهيئة التهيئة الثابتة.


(1) تشمل التعبيرات المستمر التعبيرات المستمر الحسابية أيضا (ليس فقط التعبيرات المستمرة غير المتكاملة)، عند النظر في ترتيب تهيئة الكائنات مع مدة تخزين ثابتة.

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