خطأ:× قد يكون استخدامها غير مهيأ في هذه الوظيفة في ج

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

  •  06-07-2019
  •  | 
  •  

سؤال

أنا على الحصول على هذا الخطأ

error: Access.Core may be used uninitialized in this function

و هذا هو الكود:

 static int FirstTime = 1;
 MyStruct Access;

 if (FirstTime) {
   FirstTime = 0;
   Access = Implementation();
   DoSomething(Access);
 }

 if(Other_Variable) {
    Access = Implementation2();
    DoSomething(Access);
  }

  //The Other_Variable will be set to 1 and to 0 by other part of the code

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

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

أيضا أي أفضل الخيارات لتنفيذ مرة واحدة فقط في وظيفة بدلا من استخدام متغير ثابت هي موضع ترحيب.

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

المحلول

جعل Access مثل هذا (وإزالة FirstTime و if):

static MyStruct Access = Implementation(this_b);

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

تحرير: الان مع تحديث المعلومات تقول أن لديك اثنين Implementation المهام.أول مرة كنت ترغب في استخدام واحدة, و كل مرة كنت ترغب في استخدام وظيفة أخرى.ماذا عن هذا ثم:

 // static will be false/zero by default
 static bool AlreadyCalled;
 MyStruct Access;

 if (!AlreadyCalled) {
   Access = Implementation();
   AlreadyCalled = true;
 } else {
   Access = Implementation2();
 }

اعتمادا على الاستخدام الفعلي الحالة ، قد تكون هناك طرق أفضل للتعامل مع هذا ، على الرغم من.على سبيل المثال لماذا لا يتم تحديث حالة Access, مثل هذا:

// let the default constructor initialize it
// to a plausible state
static MyStruct Access;

// use RAII to update the state of Access when this
// function returns. 
MyUpdater updater(Access);

// now, do whatever the function does. 

شيء مثل هذا MyUpdater:

struct MyUpdater {
    MyStruct &s;
    MyUpdater(MyStruct &s):s(s) { }
    ~MyUpdater() {
        s.ChangeState();
    }
};

هذا النمط يسمى RAII:يمكنك إقران بعض المعلومات المفيدة في العمل مع منشئ والمدمر محلي تخصيص الكائن.

نصائح أخرى

و @الجواب litb هي مثيرة للاهتمام. يتبع برنامج مكافئ. رمز يجمع ويعمل كما جاء في C ++، ولكن لا ترجمة في C.

#include <stdio.h>

static int newval(void) { return 3; }

void inc(void)
{
    static int a = newval();

    a++;
    printf("%d\n", a);
}

int main(void)
{
    int i;
    for (i = 0; i < 10; i++)
        inc();
    return(0);
}

ودول مجلس التعاون الخليجي يقول:

وx.c: في وظيفة "المؤتمر الوطني العراقي": x.c: 7: خطأ: العنصر مهيئ ليست ثابتة

وز ++ سعيدة جدا معها.

وهذا هو الفرق بين C و C ++ لأنني لم أكن على علم (ولكن هذا لا يصلح في 300 حرفا لذلك لا يمكن أن تجعل من تعليق، بسهولة).


وEduardo طلب أحد الأسئلة في التعليقات: "لماذا C لا نسمح لهذا وC ++ تسمح بذلك؟". منذ كان الجواب أكثر من 300 حرفا ...

وكما قالlitb في التعليقات، في C يمكنك فقط استخدام الثوابت لالمهيآت المتغيرات ثابتة. هذا هو في جزء منه لأنه يتم تعيين القيم قبل الرئيسي () ويسمى، وتسمى أي الدالات المعرفة من قبل المستخدم قبل الرئيسي () ويسمى. C ++، على النقيض من ذلك، يسمح المتغيرات العالمية وثابتة ليتم تهيئتها من قبل الصانعين (المعرفة) قبل الرئيسي () ويسمى، لذلك ليس هناك سبب لعدم سماح وظائف أخرى المعرفة من قبل المستخدم ليتم استدعاؤها للغاية، وبالتالي فإن التهيئة معقول. مع C89، هل تقتصر في المهيآت يمكنك استخدامها مع المتغيرات التلقائي (المحلية)؛ في C99، يمكنك استخدام الى حد كبير أي تعبير تهيئة أي متغير محلي.

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

إذا كنت بحاجة إلى الوصول إلى تستمر عبر المكالمات إلى وظيفة، وجعلها ثابتة.

وAccess ليس ثابت، وبالتالي فإنه يجب إنشاء في كل مكالمة.

والنظر في تبسيط قانون لشيء من هذا القبيل:

static MyStruct Access = Implementation(this_b);

وهذا يضمن أن وظيفة وسوف يطلق فقط في المرة الأولى التي يتم فيها تشغيل الطريقة وسوف أن Access عقد بين قيمة المكالمات.

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