شرح static variable




ماذا يعني "ثابت" في C؟ (12)

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

(1) هو أكثر موضوع أجنبي إذا كنت مبتدئًا ، لذلك إليك مثال:

#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

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


int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}

هذا يطبع:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

يفيد ذلك في الحالات التي تحتاج فيها إحدى الوظائف إلى الاحتفاظ ببعض الحالات بين الدعوات ، ولا ترغب في استخدام المتغيرات العامة. ومع ذلك ، كن حذرا ، ينبغي استخدام هذه الميزة لماما - فهي تجعل شيفرة الكود غير آمنة ومفهومة لفهمها.

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

نقلا عن Wikipedia :

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

انظر here here لمزيد من التفاصيل.

وللإجابة على سؤالك الثاني ، لا يشبه في C #.

في C ++ ، ومع ذلك ، يتم استخدام static أيضاً لتعريف سمات الفئة (المشتركة بين كافة الكائنات من نفس الفئة) والأساليب. في C لا توجد فئات ، لذلك هذه الميزة غير ذي صلة.

رأيت كلمة static تستخدم في أماكن مختلفة في كود C ؛ هل هذا مثل وظيفة / فئة ثابتة في C # (حيث يتم مشاركة التطبيق عبر الكائنات)؟


أنا أكره الإجابة عن سؤال قديم ، لكنني لا أعتقد أن أحدا قد ذكر كيف يشرح K & R ذلك في القسم A4.1 من "لغة البرمجة C".

باختصار ، يتم استخدام الكلمة الساكنة مع معنيين:

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

يعطي بيتر فان دير ليندن هذين المعنيين في "برمجة الخبير C":

  • داخل وظيفة ، يحتفظ بقيمته بين المكالمات.
  • على مستوى الوظيفة ، مرئية فقط في هذا الملف.

إجابة قصيرة ... يعتمد ذلك.

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

  2. المتغيرات العمومية الثابتة غير مرئية خارج الملف C الذي تم تعريفهم فيه.

  3. لا تكون الوظائف الثابتة مرئية خارج الملف C الذي تم تعريفهم فيه.


إذا قمت بالإعلان عن هذا في ملف mytest.c:

static int my_variable;

ثم يمكن فقط مشاهدة هذا المتغير من هذا الملف. لا يمكن تصدير المتغير في أي مكان آخر.

إذا قمت بالإعلان داخل دالة ، فستحتفظ قيمة المتغير بقيمته في كل مرة يتم فيها استدعاء الدالة.

لا يمكن تصدير وظيفة ثابتة من خارج الملف. لذلك في ملف * .c ، تقوم بإخفاء الوظائف والمتغيرات إذا قمت بالإعلان عنها ثابتة.


المتغير الثابت هو متغير خاص يمكنك استخدامه في وظيفة ، ويقوم بحفظ البيانات بين المكالمات ، ولا يحذفها بين المكالمات. فمثلا:

void func(){
    static int count; // If you don't declare its value, the value automatically initializes to zero
    printf("%d, ", count);
    count++;
}

void main(){
    while(true){
        func();
    }
}

الإخراج:

0 ، 1 ، 2 ، 3 ، 4 ، 5 ، ...


المتغيرات الثابتة في C لها عمر البرنامج.

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

فمثلا:

void function()
{
    static int var = 1;
    var++;
    printf("%d", var);
}

int main()
{
    function(); // Call 1
    function(); // Call 2
}

في البرنامج أعلاه ، يتم تخزين var في مقطع البيانات. عمرها هو برنامج C كامل.

بعد استدعاء الوظيفة 1 ، يصبح var 2. بعد استدعاء الدالة 2 ، يصبح var 3.

لا يتم إتلاف قيمة var بين استدعاءات الدوال.

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

يتم تخزين المتغيرات الساكنة الأولية في مقطع البيانات من البرنامج C بينما يتم تخزين المتغيرات غير المهيأة في مقطع BSS.

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

لتجربة هذا:

file1.c

static int x;

int main()
{
    printf("Accessing in same file%d", x):
}

file2.c

    extern int x;
    func()
    {
        printf("accessing in different file %d",x); // Not allowed, x has the file scope of file1.c
    }

run gcc -c file1.c

gcc -c file2.c

حاول الآن ربطها باستخدام:

gcc -o output file1.o file2.o

سيعطي خطأ رابط كما x يحتوي على نطاق الملف من file1.c و لن يكون linker قادراً على حل المرجع إلى متغير x المستخدمة في file2.c.

المراجع:

  1. http://en.wikipedia.org/wiki/Translation_unit_(programming)
  2. http://en.wikipedia.org/wiki/Call_stack

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

في أي نطاق آخر ، يعلن عن كائن يحتفظ بقيمته بين الأوقات المختلفة التي يتم فيها إدخال النطاق المحدد. على سبيل المثال ، إذا كان int يتم حذفه داخل إجراء ما:

void procedure(void)
{
   static int i = 0;

   i++;
}

تتم تهيئة قيمة 'i' إلى الصفر في أول استدعاء إلى الإجراء ، ويتم الاحتفاظ بالقيمة في كل مرة تالية يتم فيها استدعاء الإجراء. إذا تمت طباعة "i" ، فسيتم إخراج سلسلة من 0 ، 1 ، 2 ، 3 ، ...


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

1. لا يزال المتغير int الثابت في الذاكرة أثناء تشغيل البرنامج. يتم إتلاف متغير تلقائي أو تلقائي عند انتهاء استدعاء دالة حيث تم الإعلان عن المتغير.

يتم تخصيص 2.Static المتغيرات في شريحة البيانات ، وليس شريحة مكدس.

3. تتم تهيئة المتغيرات الإستراتيجية (مثل المتغيرات العالمية) على أنها صفر إذا لم يتم تهيئتها بشكل صريح. على سبيل المثال ، في البرنامج أدناه ، تتم طباعة قيمة x كـ 0 ، بينما تكون قيمة y عبارة عن بيانات قمامة. انظر هذا لمزيد من التفاصيل.

#include <stdio.h>

int main()
   {
    static int x;
    int y;
    printf("%d \n %d", x, y);
   }

من ويكيبيديا:

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


هذا يعتمد:

int foo()
{
   static int x;
   return ++x;
}

تقوم الدالة بإرجاع 1 أو 2 أو 3 أو ما إلى ذلك --- المتغير ليس على المكدس.

ميلان:

static int foo()
{
}

هذا يعني أن هذه الوظيفة لها نطاق فقط في هذا الملف. لذلك يمكن أن يكون ac و bc مختلف foo() s ، ولا يتعرض foo للأشياء المشتركة. لذا إذا قمت بتعريف foo في ac ، فلا يمكنك الوصول إليه من bc أو من أي مكان آخر.

في معظم مكتبات C جميع الوظائف "الخاصة" ثابتة ومعظم "العامة" ليست كذلك.


يظل الناس يقولون أن "الثابت" في C له معنيان. أقدم طريقة بديلة لمشاهدتها تعطيها معنىً واحدًا:

  • تطبيق "static" على عنصر يفرض هذا العنصر على خاصيتين: (a) إنه غير مرئي خارج النطاق الحالي ؛ (ب) إنها مستمرة.

السبب في ما يبدو أنه له معنيان أنه في C ، كل عنصر يمكن تطبيق "static" عليه بالفعل يحتوي على واحدة من هاتين الخاصيتين ، لذا يبدو كما لو أن هذا الاستخدام المحدد لا يشمل سوى الآخر.

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

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

ملاحظة: هذه التعليقات تنطبق فقط على C. في C ++ ، تطبيق "ثابت" على أساليب الصف يعطي الكلمة الأساسية معنى مختلفًا. وبالمثل بالنسبة لملحق الوسيطة C99 للمجموعة.


static يعني أشياء مختلفة في سياقات مختلفة.

  1. يمكنك تعريف متغير ثابت في وظيفة C. يكون هذا المتغير مرئيًا فقط في الدالة ، على الرغم من أنه يتصرف بشكل عام في أنه تمت تهيئته مرة واحدة فقط وأنه يحتفظ بقيمته. في هذا المثال ، في كل مرة تتصل فيها foo() ستقوم بطباعة رقم متزايد. يتم تهيئة متغير ثابت مرة واحدة فقط.

    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
    
  2. استخدام آخر ثابت هو عندما تقوم بتنفيذ دالة أو متغير عمومي في ملف .c ولكن لا تريد أن يكون رمزه مرئيًا خارج .obj إنشاؤه بواسطة الملف. على سبيل المثال

    static void foo() { ... }
    




static