الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

اخترنا لك(2): أستدعاء دالة قبل بدء تشغيل البر&

بدأه محمد عودة في 9 سبتمبر 2012 · 9 رد · 1,519 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله

مرحبا بكم في أخترنا لك(2)

الفهرس الرئيس لــ سلسلة أخترنا لك فى سي++

2.أستدعاء دالة قبل بدء تشغيل البرنامج Calling a Function Before Program's Startup

بعض التطبيقات تحتاج الى تشغيل دالة ما قبل ان يعمل البرنامج الرئيسي أى قبل عمل الدالة main() الرئيسة مثل عمليات سجل اﻻحداث logger وعمليات مراجعة الكمبياﻻت ... الخ، أحد الطرق المستخدمة فى ذلك هى واحدة من أفضل الخصائص (لكنها ليست معروفة) فى المترجم GCC وهي __attribute__ مع تمرير الوسيطة constructor نأخذ مثال:

#include <iostream>
using namespace std;
void beforeMain(void) __attribute__((constructor));

void beforeMain(void) {
	cout << "\nbefore main\n";
}

int main() {
	cout << "\ninside main \n";
	return 0;
}

المخرجات:

before main

inside main 

RUN SUCCESSFUL (total time: 193ms)

بما أن الحديث كان عن دالة تعمل قبل بدء البرنامج فلابد ان نفكر فى دالة تعمل بعد انتهاء البرنامج بنفس الفكرة السابقة وهي __attribute__ ولكن هذة المرة نمرر الوسيطة destructor نأخذ مثال يشتمل على كلا من النقطة السابقة والحالية معا :

#include <iostream>
using namespace std;

void my_ctor(void) __attribute__((constructor));
void my_dtor(void) __attribute__((destructor));

void my_ctor(void) {
	cout << "hello before main()" << endl;
}

void my_dtor(void) {
	cout << "bye after main()\n";
}

int main(void) {
	cout << "hello\n";
	return 0;
}

المخرجات:

hello before main()
hello
bye after main()

RUN SUCCESSFUL (total time: 181ms)

وهناك طرق أخري منها:

  • فكرة دور حول دالة بناء كائن معلن على مستوي البرنامج.
  • وايضا فكرة عن طريق المتغيرات العامة الساتيتكية globle static.

ان شاء الله نتناولها سويا او احد اﻻعضاء يتفضل مشكورا بالنقاش حولها.

والى لقاء فى تلميحة جديدة فى عالم سي و سي++

تم تعديل هذه المشاركة بواسطة محمد عودة في 17 سبتمبر 2012 في 09:14 — السبب: تنقيح وتصحيح

1

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#2

توجد 3 طرق "قياسية" :

  1. يمكننا إنشاء فئة باسم Welcome مثلا, و نضع الأوامر المُراد إظهارها داخل دالة البناء ثم ننشئ كائن جديد من الفئة Welcome قبل الدخول في الدالة الرئيسية, هكذا :
    #include <iostream>
    
    class Welcome {
    public:
    
        Welcome() {
            std::cout << "Welcome to C++ !" << std::endl;
        }
    } Welcome;
    
    int main() {
        return 0;
    }


  2. استخدام الماكرو #define :
    #include <stdio.h>
    #define return printf("Welcome to C !!");
    
    void main() {
        return;
    }


  3. التلاعب باستدعاء الدوال :
    #include <iostream>
    
    int Welcome() {
        std::cout << "Welcome To C++" << std::endl;
        return 0;
    }
    
    int main() {
        return (Welcome());
    }

2
#3
اقتباس
توجد 3 طرق "قياسية" :

كلامك أخي أحمد يتم تنفيذه داخل الmain طبعاً ماعدا أول فكرة....

ولكن كلام الأخ محمد .. بتنفيذ تابع مستقل عن أي فئة قبل تنفيذ الmain تماماً ...

ثم إن الطريقة الثانية التي ذكرتها غير قياسية wink.gifwink.gif فالدالة main يجب أن تعيد int wink.gif

#4

لإضافة user-defined global initializer:

#include<stdio.h>
#include<conio.h>

#pragma section(".CRT$XCU",long,read)

int __cdecl _init_func1(void) {
    printf("Initialization 1...\n");
    return 0;
}
__declspec(allocate(".CRT$XCU")) static int  (__cdecl *_INIT_FUNC1)() = _init_func1;

int __cdecl _init_func2(void) {
    printf("Initialization 2...\n");
    return 0;
}
__declspec(allocate(".CRT$XCU")) static int  (__cdecl *_INIT_FUNC2)() = _init_func2;

int main() {
	printf("main\n");
	getch();
    return 0;
}

output:

Initialization 1...
Initialization 2...
main

تم تعديل هذه المشاركة بواسطة khatibe_30 في 9 سبتمبر 2012 في 14:04

[سبحان الله و بحمده, سبحان الله العظيم]

#5
اقتباس
كلامك أخي أحمد يتم تنفيذه داخل الmain طبعاً ماعدا أول فكرة

الطريقة الأولى وضعتُها كإجابة على السؤال المطروح أما باقي الطرق فهي للإفادة فقط.

اقتباس
ثم إن الطريقة الثانية التي ذكرتها غير قياسية :wink: :wink: فالدالة main يجب أن تعيد int :wink:

عندما يتم استخدام void, ستتم دائما إعادة صفر.

عندما يتم استخدام void و عند استخدام return للخروج من الداله او عندما لا توجد return, يتم اضافة الكود التالى بعد كود المستخدم :

xor eax, eax

و هذه طريقه سريعه لجعل eax بصفر و بعدها يتم حفظ قيمة eax و من ثم اجراء عمليات إخلاء ذاكرة الـ stack, بعدها يتم إرجاع قيمة eax مرة أخرى بصفر, يليها استدعاء دالة إنهاء البرنامج و حينها يكون eax بصفر و هذه هي الـ Exit Status و التى تعنى operation completed successfully.

#6
اقتباس
يليها استدعاء دالة إنهاء البرنامج

نعم لاحظتها عندما تتبعت البرنامج بF11 قبل فترة ..

اقتباس
xor eax, eax

هل تعني أنها تحدث تلقائياً ... إذا لا داعي للreturn .. إلا في حالة عدم إكمال البرنامج

#7

أخي محمد عودة ، الطريقة التي استخدمتها تصلح في السي++ فهل من طريقة تصلح في لغة السي ؟ غير الطريقة التي وضعها الأخ ياسين laugh.gif ... أنا في انتظار جواب شاف و مقنع + لغة السي لا تدعم :

المشيد :

tbXbC.jpg

و المهدم :

TvsYU.jpg

تم تعديل هذه المشاركة بواسطة Hamza+C+ASM في 9 سبتمبر 2012 في 14:30

rS3eY.png
#8

بكل بساطة يمكننا فعل هذا وحسب smile.gif :

#include <stdio.h>
extern void BeforeMain(){
printf("\n\n\t je suis gai car je suis content :) !!!\n\n");
}

main(){
 	BeforeMain();
 	printf("\t Malheureusement, je suis la fonction principale :( ");
 	getchar();
}

و النتيجة : 019.gif

oJ2c5.png

rS3eY.png
#9

بالنسبة ﻵلية عمل الكود التالي الذي تفضل أخي أحمد الشنقيطي بعرضة تتلخص فى ان الكائن العام على متسوي البرنامج Welcome يتم بنائه قبل بداية البرنامج وعندما يتم بناءة فأن دالة البناء اﻻفتراضية فية تعمل ومن ثم فأن يتم عرض جملة Wellcom to C+++ !

انتبة: اخونا احمد استخدم ميزة كائن بدون هوية مؤقت Anonymous class objects ﻻنك قد تقول لما اسم الكائن لة نفس اسم الفئة؟

اقتباس
#include <iostream>
class Welcome {
public:
    Welcome() {
        std::cout << "Welcome to C++ !" << std::endl;
    }
} Welcome;

int main() {
    return 0;
}

اقتباس
فهل من طريقة تصلح في لغة السي ؟

نعم أخي Hamza+C+ASM

انظر:

#include <stdio.h>
#include <stdlib.h>

void my_ctor(void) __attribute__((constructor));
void my_dtor(void) __attribute__((destructor));

void my_ctor(void) {
	printf("hello before main()\n");
}

void my_dtor(void) {
	printf("bye after main()\n");
}

int main(void) {
	printf("hello\n");
	return 0;
}

مخرجات:

hello before main()
hello
bye after main()

لكن اخي احذر فهذة شئ خاص بالمترجم GCC compiler on Linux انا ﻻ ادري اي المترجمات تستخدم عليك بالرجوع الى دليل استخدام مترجمك الخاص

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#10

اشتغلت أخي محمد شكرا لك حبيبي + طريقة رائعة خصوصا و أن مايكروسوفت ربما تستعمل هذه الطريقة ولو بشكل مغاير،،،

أنظر حبيبي هنا : cool.gif

xbTRN.png

rS3eY.png

مواضيع مشابهة