سؤال

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

ونقطة واحدة إضافية من ملاحظة: السبب الرئيسي لاستخدام مهيئ المعينة وinitalizing كما NOT أول عضو في الاتحاد. أيضا، العالقة مع معيار C ++ أو ANSI C هو زائد من أجل الحفاظ على التوافق مع المجمعين أخرى (وأنا أعلم عن ملحقات GNU التي توفر شيء من هذا القبيل المهيآت معين دون C99).

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

المحلول

وأنا لست متأكد من أنك يمكن أن تفعل ذلك في C ++. للأشياء التي تحتاج إلى تهيئة باستخدام المهيآت المعينة، يمكنك وضع هذه على حدة في ملف .c تجميعها وC99، منها مثلا:

// In common header file
typedef union my_union
{
    int i;
    float f;
} my_union;

extern const my_union g_var;

// In file compiled as C99
const my_union g_var = { .f = 3.14159f };

// Now any file that #include's the header can access g_var, and it will be
// properly initialized at load time

نصائح أخرى

وبناء على الجواب شينغ ييب، وومع الاستفادة من الوقت لمدة 3 سنوات، وC ++ 11 يمكن أن تضمن الآن تجميع وقت التهيئة:

union Bar
{
    constexpr Bar(int a) : a_(a) {}
    constexpr Bar(float b) : b_(b) {}
    int a_;
    float b_;
};

extern constexpr Bar bar1(1);
extern constexpr Bar bar2(1.234f);

والجمعية:

    .globl  _bar1                   ## @bar1
    .p2align    2
_bar1:
    .long   1                       ## 0x1

    .globl  _bar2                   ## @bar2
    .p2align    2
_bar2:
    .long   1067316150              ## float 1.23399997
#ifdef __cplusplus
struct Foo
{
    Foo(int a, int b) : a(a), b(b) {}
    int a;
    int b;
};

union Bar
{
    Bar(int a) : a(a) {}
    Bar(float b) : b(b) {}
    int a;
    float b;
};

static Foo foo(1,2);
static Bar bar1(1);
static Bar bar2(1.234f);
#else 
 /* C99 stuff */
#endif // __cplusplus

في الاتحاد C ++ يمكن أن يكون الصانعين أيضا. قد يكون هذا هو ما تريد؟

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

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

#include <iostream>

using namespace std;

extern "C" 
{
    typedef struct stuff
    {
        int x;
        double y;
    } things;
}

int main()
{
    things jmcd = { jmcd.x = 12, jmcd.y = 10.1234 };
    cout << jmcd.x << " " << jmcd.y << endl;
    return 0;
}

وهذا له مظهر مماثل جدا للالمهيآت أسلوب C99 المعينة مع التحذير سأذكر لاحقا. (ومنها يمكنك أن من المحتمل الانتهاء من هذه في __cplusplus #IFDEF إذا أردت البنية التي سيتم تجميعها من قبل أي) الإصدار الثاني من التعليمات البرمجية نظرت إلى هذا:

#include <iostream>

using namespace std;

extern "C" 
{
    typedef struct stuff
    {
        int x;
        double y;
    } things;
}


int main()
{
    things jmcd;
    jmcd.x = 12;
    jmcd.y = 10.1234;
    cout << jmcd.x << " " << jmcd.y << endl;
    return 0;
}

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

main:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $0, 12(%esp)
    movl    $0, 16(%esp)
    movl    $0, 20(%esp)
    movl    $12, 12(%esp)
    movl    12(%esp), %eax
    movl    %eax, 12(%esp)
    fldl    .LC0
    fstpl   16(%esp)
    fldl    16(%esp)
    fstpl   16(%esp)
    movl    12(%esp), %eax
    movl    %eax, 4(%esp)
    fildl   4(%esp)
    fldl    16(%esp)
    faddp   %st, %st(1)
    fnstcw  2(%esp)
    movzwl  2(%esp), %eax
    movb    $12, %ah
    movw    %ax, (%esp)
    fldcw   (%esp)
    fistpl  4(%esp)
    fldcw   2(%esp)
    movl    4(%esp), %eax
    leave
    ret
    .cfi_endproc

والمثال الثاني يشبه:

main:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $12, 12(%esp)
    fldl    .LC0
    fstpl   16(%esp)
    movl    12(%esp), %eax
    movl    %eax, 4(%esp)
    fildl   4(%esp)
    fldl    16(%esp)
    faddp   %st, %st(1)
    fnstcw  2(%esp)
    movzwl  2(%esp), %eax
    movb    $12, %ah
    movw    %ax, (%esp)
    fldcw   (%esp)
    fistpl  4(%esp)
    fldcw   2(%esp)
    movl    4(%esp), %eax
    leave
    ret
    .cfi_endproc

وتم إنشاؤها كل من هذه مع أمر g++ -O0 -S main.cpp. ومن الواضح أن إنشاء مثل حدسي أقل كفاءة شفرة تشغيل أكثر كفاءة من حيث عدد من التعليمات. من ناحية أخرى، هناك عدد قليل من الحالات التي يمكن أن أتصور بعض الإرشادات يجري حرجة. (من ناحية أخرى، وأنا حقا صعوبة في فهم التجمع لم يكتب من قبل البشر، لذلك ربما أنا في عداد المفقودين شيء ...) وأعتقد أن هذا يوفر حلا، وإن كان متأخرا، على السؤال جيمس طلب منها ذلك. والشيء التالي الذي يجب اختبار هو إذا كان يسمح للنفس التهيئة في C99. اذا كان يعمل، وأعتقد أنه يعالج تماما مشكلة جيمس.

تنويه: ليس لدي أي فكرة ما إذا كان هذا يعمل أو سلوك مشابه لأي المجمعين أخرى غير ز ++

وتقرير حفرة الجافة:

ونظرا

struct S {
  int mA;
  int mB;
  S() {}
  S(int b} : mB(b) {} // a ctor that does partial initialization
};

وحاولت اشتقاق S1 من S، حيث استدعاء منشئ مضمنة الافتراضي S1 لS (الباحث) وتمرير قيمة الثابت تلوينها ...

struct S1 {
  S1() : S(22) {}
} s1;

... ثم جمعها مع دول مجلس التعاون الخليجي 4.0.1 -O2 -S. وكان الأمل أن محسن أن نرى أن s1.mB سيكون بالضرورة 22 وتعيين القيمة التي في وقت الترجمة، ولكن من المجمع ...

    movl    $22, 4+_s1-"L00000000002$pb"(%ebx)

... يبدو أن الشفرة التي تم إنشاؤها لا التهيئة في وقت التشغيل قبل الرئيسي. حتى لو عملت، فإنه يكاد يكون تحويل البرمجي كما C99 وسيكون لها حل مشكلة من اشتقاق فئة لكل كائن أردت تهيئة. لذلك، لا تهتم.

والتعليمة البرمجية التالية بتصنيف بدون مشاكل مع g ++:

#include <iostream>

struct foo
{
  int a;
  int b;
  int c;
};

union bar
{
  int a;
  float b;
  long c;
};

static foo s_foo1 = {1,2,3};
static foo s_foo2 = {1,2};
static bar s_bar1 = {42L};
static bar s_bar2 = {1078523331}; // 3.14 in float


int main(int, char**)
{
  std::cout << s_foo1.a << ", " <<
               s_foo1.b << ", " <<
               s_foo1.c << std::endl;

  std::cout << s_foo2.a << ", " <<
               s_foo2.b << ", " <<
               s_foo2.c << std::endl;

  std::cout << s_bar1.a << ", " <<
               s_bar1.b << ", " <<
               s_bar1.c << std::endl;

  std::cout << s_bar2.a << ", " <<
               s_bar2.b << ", " <<
               s_bar2.c << std::endl;

  return 0;
}

وها هي النتيجة:

$ g++ -o ./test ./test.cpp
$ ./test
1, 2, 3
1, 2, 0
42, 5.88545e-44, 42
1078523331, 3.14, 1078523331

والشيء الوحيد مع المهيآت C ++ هو أنك تحتاج إلى تهيئة جميع عناصر البنية أو سيتم تهيئة بقية مع الأصفار. لا يمكنك انتقاء واختيار. ولكن ينبغي أن يكون لا يزال موافق لحالة استخدامك.

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

ونقطة واحدة إضافية من ملاحظة: السبب الرئيسي لاستخدام مهيئ المعينة وinitalizing كما NOT أول عضو في اتحاد

لذلك تحتاج إلى استخدام "الحل" هو موضح في المثال حيث I تعيين عضو "تعويم" من خلال توفير قيمة كثافة مماثلة. انها قليلا من الإختراق، ولكن إذا كان لا يحل مشكلتك.

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