سؤال

سألت السؤال عن C-نوع الأحجام التي أحصل على إجابة جيدة جدا ولكن أدركت أنني قد لا صياغة السؤال بشكل جيد للغاية أن تكون مفيدة بالنسبة لي الغرض.

خلفيتي كان من مهندس كمبيوتر قبل أن ينتقل إلى مهندس البرمجيات لذلك أود المعماريات و دائما أفكر في صنع VM.لقد انتهيت للتو من مشروع مثير للاهتمام صنع VM على Java الذي أنا فخور جدا مع.ولكن هناك بعض المشاكل القانونية لا أستطيع مفتوح المصدر الآن وأنا حاليا لديك بعض الوقت الحر.لذلك أريد أن أرى ما إذا كنت يمكن أن تجعل آخر VM على C (مع سرعة أفضل) فقط من أجل متعة والتعليمية.

الشيء هو أنني لست C برنامج آخر مرة كتبت غير التوافه ج المشكلة أكثر من 10 سنوات.كنت Pascal, Delphi, و الآن جافا و PHP مبرمج.

هناك عدد من العقبات التي لا يمكن التنبؤ بها و أنا أحاول معالجة واحد و هو الوصول إلى مكتبة موجودة (في جافا, انعكاس يحل هذه المشكلة).

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

int main(void) {
    // Prepare stack
    int   aStackSize = 1024*4;
    char *aStackData = malloc(aStackSize);

    // Initialise stack
    VMStack aStack;
    VMStack_Initialize(&aStack, (char *)aStackData, aStackSize);

    // Push in the parameters
    char *Params = VMStack_CurrentPointer(&aStack);
    VMStack_Push_int   (&aStack, 10  ); // Push an int
    VMStack_Push_double(&aStack, 15.3); // Push a double

    // Prepare space for the expected return
    char *Result = VMStack_CurrentPointer(&aStack);
    VMStack_Push_double(&aStack, 0.0); // Push an empty double for result

    // Execute
    void (*NativeFunction)(char*, char*) = &Plus;
    NativeFunction(Params, Result); // Call the function

    // Show the result
    double ResultValue = VMStack_Pull_double(&aStack); // Get the result
    printf("Result:  %5.2f\n", ResultValue);               // Print the result

    // Remove the previous parameters
    VMStack_Pull_double(&aStack); // Pull to clear space of the parameter
    VMStack_Pull_int   (&aStack); // Pull to clear space of the parameter

    // Just to be sure, print out the pointer and see if it is `0`
    printf("Pointer: %d\n", aStack.Pointer);

    free(aStackData);
    return EXIT_SUCCESS;
}

دفع سحب الاحتجاج وظيفة الأم يمكن أن يكون سببها رمز بايت (هذا هو كيف VM سيتم في وقت لاحق).

من أجل استكمال (حتى يمكنك أن تجرب ذلك على آلة), هنا هو رمز المكدس:

typedef struct {
    int  Pointer;
    int  Size;
    char *Data;
} VMStack;

inline void   VMStack_Initialize(VMStack *pStack, char *pData, int pSize) __attribute__((always_inline));
inline char   *VMStack_CurrentPointer(VMStack *pStack)                    __attribute__((always_inline));
inline void   VMStack_Push_int(VMStack *pStack, int pData)                __attribute__((always_inline));
inline void   VMStack_Push_double(VMStack *pStack, double pData)          __attribute__((always_inline));
inline int    VMStack_Pull_int(VMStack *pStack)                           __attribute__((always_inline));
inline double VMStack_Pull_double(VMStack *pStack)                        __attribute__((always_inline));

inline void VMStack_Initialize(VMStack *pStack, char *pData, int pSize) {
    pStack->Pointer = 0;
    pStack->Data    = pData;
    pStack->Size    = pSize;
}

inline char *VMStack_CurrentPointer(VMStack *pStack) {
    return (char *)(pStack->Pointer + pStack->Data);
}

inline void VMStack_Push_int(VMStack *pStack, int pData) {
    *(int *)(pStack->Data + pStack->Pointer) = pData;
    pStack->Pointer += sizeof pData; // Should check the overflow
}
inline void VMStack_Push_double(VMStack *pStack, double pData) {
    *(double *)(pStack->Data + pStack->Pointer) = pData;
    pStack->Pointer += sizeof pData; // Should check the overflow
}

inline int VMStack_Pull_int(VMStack *pStack) {
    pStack->Pointer -= sizeof(int);// Should check the underflow
    return *((int *)(pStack->Data + pStack->Pointer));
}
inline double VMStack_Pull_double(VMStack *pStack) {
    pStack->Pointer -= sizeof(double);// Should check the underflow
    return *((double *)(pStack->Data + pStack->Pointer));
}

على وظيفة الأم الجانب ، أنا خلق التالية لغرض الإختبار:

// These two structures are there so that Plus will not need to access its parameter using
//    arithmetic-pointer operation (to reduce mistake and hopefully for better speed).
typedef struct {
    int    A;
    double B;
} Data;
typedef struct {
    double D;
} DDouble;

// هنا هي وظيفة مساعد لعرض الفراغ PrintData(البيانات *pData ، DDouble *pResult) { printf("%5.2 f + %5.2 f = %5.2 f ", pData->A*1.0, pData->B, pResult->د) ؛ }

// بعض وظيفة الأم الفراغ زائد(char* pParams, char* pResult) { البيانات *د = (البيانات *)pParams;// الوصول إلى البيانات دون الحسابي المؤشر العملية DDouble *DD = (DDouble *)pResult;// نفس للعودة DD->D = D->A + D->B;PrintData(د ، د د);}

عندما أعدم ، رمز أعلاه العوائد:

10.00 + 15.30 = 25.30
Result:  25.30
Pointer: 0

هذا العمل جيدا على الجهاز الخاص بي (لينكس x86 32bits دول مجلس التعاون الخليجي-C99).وسوف يكون لطيفا جدا إذا كان هذا يعمل على نظام التشغيل الأخرى/العمارة أيضا.ولكن هناك على الأقل ثلاثة المتعلقة بالذاكرة issures يجب أن تكون على علم.

1).حجم البيانات - يبدو إن تجميع كل VM وظائف الأم باستخدام نفس المترجم في نفس العمارة, حجم الأنواع يجب أن تكون هي نفسها.

2).Endianness - نفسه مع حجم البيانات.

3).الذاكرة المحاذاة - وهو المشكلة كما الحشو بايت ويمكن أن يضاف في البنية ولكن من الصعب أن تزامن ذلك عند إعداد المعلمة المكدس (ليس هناك طريقة لمعرفة كيف يتم إضافة الحشو ما عدا الثابت ترميز).

أسئلتي هي:

1).لو كنت أعرف حجم أنواع, هل هناك طريقة لتعديل دفع وسحب وظيفة بالضبط مزامنة مع البنية الحشو ؟ (تعديل للسماح مترجم يعتني بها مثل Datasize و Endians مشاكل).

2).إذا كنت حزمة هيكل واحد (باستخدام #pragma pack(1));(2.1) هل جزاء أداء مقبول ؟ و (2.2) سوف برنامج الاستقرار يكون في خطر ؟

3).ماذا عن الحشو بنسبة 2,4, أو 8 ؟ التي ينبغي أن تكون جيدة العامة 32 أو 64 بت ؟

4).يمكنك أن توجه لي إلى توثيق دقيق الحشو خوارزمية دعونا نقول عن دول مجلس التعاون الخليجي على x86 ؟

5).هل هناك طريقة أفضل ؟

ملاحظة:عبر منصة ليس هدفي النهائي ولكن أنا لا يمكن أن تقاوم.أيضا الأداء ليس هدفي في أقرب وقت كما أنها ليست قبيحة جدا.كل هذه هي من أجل المتعة والتعلم.

آسف لغتي الإنجليزية و طويلة جدا بعد.

شكرا للجميع مقدما.

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

المحلول

تعليقات عرضية

وهذه البنود هي الأولى عرضية إلى الأسئلة التي طلبت، ولكن ...

// Execute
void (*NativeFunction)(char*, char*) = &Plus;
NativeFunction(Params, Result); // Call the function

وأعتقد أنك ربما ينبغي استخدام 'باطل *' بدلا من 'شار * هنا. كنت أود أن يكون أيضا typedef ولنوع وظيفة مؤشر:

typedef void (*Operator)(void *params, void *result);

وبعد ذلك يمكنك كتابة:

Operator NativeFunction = Plus;

وظيفة الفعلية سيتم تعديل جدا - ولكن بشكل طفيف جدا:

void Plus(void *pParams, void *pResult)

وبالإضافة إلى ذلك، لديك مشكلة تسمية الثانوية - هذه هي وظيفة "IntPlusDoubleGivesDouble () '، بدلا من أن يكون الغرض العام" إضافة أي نوعين' وظيفة

.

الأجوبة المباشرة على الأسئلة

<اقتباس فقرة>   

1). لو كنت أعرف حجم أنواع، هناك طريقة لتعديل الشد والجذب وظيفة مزامنة بالضبط مع الحشو البنية؟ (تعديل للسماح المترجم يعتني عليه Datasize والمشاكل Endians).

وليس هناك طريقة سهلة للقيام بذلك. على سبيل المثال، النظر فيما يلي:

struct Type1
{
     unsigned char byte;
     int           number;
};
struct Type2
{
     unsigned char byte;
     double        number;
};

في بعض أبنية (32 بت أو 64 بت SPARC، على سبيل المثال)، فإن هيكل Type1 يكون 'رقم' الانحياز في حدود 4 بايت، إلا أن هيكل TYPE2 يكون 'رقم' محاذاة على 8- الحدود بايت (وقد يكون لديك 'مزدوج طويلة "على حد 16 بايت). سيكون لديك استراتيجية "دفع العناصر الفردية" عثرة مؤشر المكدس بواسطة 1 بعد دفع قيمة 'بايت' - لذلك كنت ترغب في تحريك مؤشر المكدس بواسطة 3 أو 7 قبل دفع 'رقم'، إذا كان مؤشر مكدس ليس بالفعل بشكل مناسب الانحياز. جزء من وصف VM الخاص بك وسوف تكون التحالفات المطلوبة لأي نوع معين؛ سوف تحتاج رمز دفع المقابلة لضمان المحاذاة الصحيحة قبل دفع.

<اقتباس فقرة>   

2). إذا أنا أحزم هيكل من جانب واحد (باستخدام #pragma حزمة (1))؛ (2.1) وسوف تكون عقوبة الأداء مقبولة؟ و (2.2) وسوف يكون برنامج الاستقرار في خطر؟

في x86 و x86_64 آلات، إذا كنت حزمة البيانات، سوف تتكبدها جزاء أداء للالوصول إلى البيانات المنحرفة. على الأجهزة مثل SPARC <س> أو باور (لكل mecki )، سوف تحصل على خطأ حافلة أو شيء مماثل بدلا من ذلك - يجب الوصول إلى البيانات في انحيازها المناسبة. قد حفظت بعض مساحة الذاكرة - بتكلفة في الأداء. كنت تفعل أفضل لضمان الأداء (وهو هنا تشمل "أداء بشكل صحيح بدلا من تحطمها ') في التكلفة الحدية في الفضاء.

<اقتباس فقرة>   

و3). ماذا عن الحشو من 2،4 أو 8؟ والتي يجب أن تكون جيدة للعام نظام 32 أو 64 بت؟

في SPARC، تحتاج إلى وسادة نوع الأساسية N-بايت إلى الحدود N بايت. على x86 و سوف تحصل على أفضل أداء إذا كنت تفعل الشيء نفسه.

<اقتباس فقرة>   

و4). يمكنك توجيه لي إلى وثائق لخوارزمية الحشو الدقيقة دعنا نقول لدول مجلس التعاون الخليجي على إلى x86؟

وأنت سيكون لديك لقراءة دليل .

<اقتباس فقرة>   

و5). هل هناك طريقة أفضل؟

ملحوظة أن خدعة "Type1 'مع حرف واحد يليه نوع يمنحك شرط التوافق - ربما باستخدام' offsetof () 'ماكرو من <stddef.h>:

offsetof(struct Type1, number)

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

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

نصائح أخرى

وظيفة مثيرة للاهتمام وتبين أن كنت قد وضعت في الكثير من العمل. تقريبا مثالية نشر SO.

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

<اقتباس فقرة>   

1). لو كنت أعرف حجم أنواع، هناك طريقة لتعديل الشد والجذب وظيفة مزامنة بالضبط مع الحشو البنية؟ (تعديل للسماح المترجم يعتني عليه Datasize والمشاكل Endians).

هل هذا من جهة نظر الأداء فقط؟ هل تخطط لإدخال مؤشرات جنبا إلى جنب مع أنواع الحسابية الأم؟

<اقتباس فقرة>   

2). إذا أنا أحزم هيكل من جانب واحد (باستخدام #pragma حزمة (1))؛ (2.1) وسوف تكون عقوبة الأداء مقبولة؟ و (2.2) وسوف يكون برنامج الاستقرار في خطر؟

وهذا هو الشيء المعرفة من قبل التنفيذ. لا شيء يمكنك الاعتماد على عبر منصات.

<اقتباس فقرة>   

و3). ماذا عن الحشو من 2،4 أو 8؟ والتي يجب أن تكون جيدة للعام نظام 32 أو 64 بت؟

والقيمة التي مباريات مع حجم الكلمة الأصلي يجب أن تعطيك أفضل أداء.

<اقتباس فقرة>   

و4). يمكنك توجيه لي إلى وثائق لاسمحوا الحشو خوارزمية المحدد نقول لدول مجلس التعاون الخليجي على إلى x86؟

وأنا لا أعرف من أي من أعلى رأسي. ولكن رأيت رمز مشابهة ل هذا البحث المستخدمة.

ملحوظة، التي يمكنك تحديد سمات المتغيرات استخدام دول مجلس التعاون الخليجي (التي لديها أيضا ما يسمى default_struct __attribute__((packed)) أن إيقاف الحشو).

هناك بعض الأسئلة هنا, العديد منهم الحصول على متشابكة في بعض مسائل التصميم ولكن بالنسبة لمعظمنا - يمكننا أن نرى ما كنت تعمل نحو ( dirkgently نشرت وأنا أكتب حتى تستطيع أن ترى أنت توليد الاهتمام ) يمكننا أن نفهم اللغة الإنجليزية جيدا بما فيه الكفاية أن ما كنت تعمل نحو هو المترجم بعض القضايا وبعض لغة تصميم القضايا - يصبح من الصعب العمل السؤال ولكن أن كنت تعمل بالفعل في JNI هناك أمل ...

لشيء واحد, وأود أن محاولة للحصول على بعيدا عن pragmas;العديد من الناس ، كثيرة جدا سوف أتفق مع ذلك.بالنسبة الكنسي مناقشة لماذا نرى مبررا د لغة موقف بشأن هذه المسألة.آخر, هناك 16-بت مؤشر دفن في التعليمات البرمجية الخاصة بك.

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

وقال مع ذلك, يذهب هنا:

  1. ج-نوع الأحجام ما هو نوع أحجام?
  2. مهندس كمبيوتر قبل أن ينتقل إلى مهندس البرمجيات من أي وقت مضى درس ميكروكنترولر?Hava نظرة على بعض من لا لانكستر العمل.
  3. باسكال, دلفي, و الآن جافا و PHP مبرمج. تلك هي نسبيا إزالتها من قاعدة أساسية في الهندسة المعمارية من المعالجات ، على الرغم من الكثير من الأشخاص سوف تظهر أو محاولة لإظهار كيف يمكن استخدامها لكتابة قوية وأساسية الروتينية.أقترح أن تبحث في ديفيد إيك هو العودية النسب محلل لنرى بالضبط كيف يمكنك البدء في دراسة هذه المسألة.كما كينيث يزيد من شدة الصوت لديه تنفيذ "الصغير" الذي هو المترجم الفعلي.لقد وجدت شيئا منذ وقت ليس ببعيد أن أعتقد كان يسمى asm دوت أورج ...متقدمة جدا وقوية جدا العمل المتاحة للدراسة هناك وإنما هو الطويل أن تبدأ الكتابة في المجمع الراغبين في الحصول على مترجم العلم.أضف إلى ذلك أن معظم أبنية الاختلافات التي لا تتفق من معالج واحد إلى آخر.
  4. الوصول إلى مكتبة موجودة

هناك العديد من يبس حولها ، جافا بعض منها جيدة.أنا لا أعرف عن الآخرين.نهج واحد هو محاولة لكتابة lib.جافا لديها قاعدة جيدة و يترك مجالا الناس ترغب في محاولة الخروج بشيء أفضل.تبدأ مع تحسين كانوث-موريس-برات أو شيء:لا يوجد نقص في أماكن تبدأ.محاولة الكمبيوتر خوارزميات البرمجة الدليل و بالتأكيد ننظر في قاموس الخوارزميات وهياكل البيانات في NIST

  1. always_inline

ليس بالضرورة ، انظر دوف البولكا - عامل يحمل شهادة الدكتوراه في CS وكذلك هو يبرع الكاتب في المناطق حيث الوقت-الكفاءة / الموثوقية المتانة حتى لا تخضع بعض "نموذج الأعمال" نموذج اينما نحصل على بعض "أوه!هذا لا يهم" على القضايا التي في الواقع لا يهم.

كما الختام ، القياس والتحكم يشكلون أكثر من 60% من السوق الفعلية على إنجاز مهارات البرمجة كما تصفون.لسبب ما نسمع في معظمها حول نموذج الأعمال التجارية.واسمحوا لي أن أطلعكم وداخل نبأ سار علي من مصدر موثوق.من 10 ٪ إلى 60 ٪ أو أكثر الفعلية السلامة و المخاطر تأتي من المركبات القضايا من يأتي من السرقة, سرقة هذا النوع من الشيء.وأنك لن تسمع نداءات "90 يوما تكسير المعادن في مقاطعة استخراج المعادن faciltiy!" للحصول على تذاكر المرور ، في الواقع معظم الناس لا يدركون حتى المرور الاستشهادات ( N. A.- الولايات المتحدة الأمريكية) فئة 4 جنحة فعلا يمكن تصنيفها على هذا النحو.

يبدو لي أن كنت قد اتخذت خطوة جيدة نحو بعض العمل الجيد ، ...

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