سؤال

في ج لدي هذا الكود قطعة:

int a;
a = 10 + 5 - 3

أريد أن أسأل:أين هو (10+5-3) المخزنة ؟ (بقدر ما أعرف ، a يقع على المكدس ، ما رأيك (10+5-3)?كيف هذا rvalue على حسابها؟)

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

المحلول

عادة, r-value "تخزين" داخل البرنامج نفسه.

وبعبارة أخرى ، فإن المترجم نفسه (قبل البرنامج هو تشغيل أي وقت مضى) يحسب 10 + 5 - 3 قيمة (يمكن القيام بذلك نظرا لأنه هو كل شيء على أساس ثابت فورية القيم) ، تنبعث منه رمز التجميع لتخزين نتيجة هذا الحساب في أي l-قيمة assignement (في هذه الحالة ، متغير اسمه a ، الذي مترجم ربما يعرف عنوان نسبي إلى شريحة بيانات أصل الأنواع).

R-القيمة بقيمة 12 وعليه وجدت داخل الثنائية البرنامج داخل الجمعية التعليمات التي يبدو مثل

  mov <some dest, typically DS-relative>, $0C 

$0C هو "r-value".

إذا كان r-value حدث نتيجة الحساب التي يمكن أن يتم إلا في وقت التشغيل ، أقول إذا الكامنة ج كود:a = 17 * س ؛ // × بعض وقت التشغيل var r-value أيضا أن "المخزن" (أو بالأحرى تتحقق) سلسلة من التعليمات داخل البرنامج الثنائية.الفرق بسيط "mov دست imm" سبق هو أن الأمر سيستغرق عدة تعليمات لتحميل المتغير x في المجمع ، ضرب من قبل 17 وتخزين النتيجة في العنوان حيث المتغير a.فمن الممكن أن المترجم قد "يأذن نفسها" ;-) استخدام المكدس لبعض المتوسطة نتيجة إلخ.ولكن هذا سيكون
أ) تماما مترجم تعتمد
ب) transiant
ج) عادة ما تنطوي فقط جزء r-value
ولذلك فمن الأسلم أن نقول أن r-القيمة مفهوم الترجمة الوقت الذي يتم تغليف في أجزاء من البرنامج (لا بيانات) و لا يتم تخزينها في أي مكان ولكن في البرنامج الثنائية.

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

نصائح أخرى

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

 LOAD AX, i
 SUB AX, j
 ADD AX, k

لحساب مثل هذا التعبير "تخزين" IT في Accumulator تسجيل الفأس، قبل تعيينه إلى موقع الذاكرة STORE AX, dest أو ما شابه ذلك. سأكون مندهشا جدا إذا كان هناك مترجم محسن حديث في هندسة وحدة المعالجة المركزية شبه الكريمة (نعم، X86 المدرجة! -) اللازمة لسجل السجلات إلى الذاكرة لأي تعبير بسيط بشكل معقول!

هذا هو مترجم يعتمد. عادة ما يتم حساب القيمة (12) من قبل المحول البرمجي. ثم يتم تخزينها في التعليمات البرمجية، عادة كجزء من تحميل / نقل تعليمات التجميع الفوري.

حيث يخزنها في الواقع تماما يصل إلى المحول البرمجي. المعيار لا يملي هذا السلوك.

أ عادي يمكن رؤية المكان من خلال تجميع التعليمات البرمجية في الواقع والنظر في إخراج المجمع:

int main (int argc, char *argv[]) {
    int a;
    a = 10 + 5 - 3;
    return 0;
}

التي تنتج:

        .file   "qq.c"
        .def    ___main;
            .scl    2;
            .type   32;
        .endef
        .text
.globl _main
        .def    _main;
            .scl    2;
            .type   32;
        .endef
_main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        addl    $15, %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        movl    %eax, -8(%ebp)
        movl    -8(%ebp), %eax
        call    __alloca
        call    ___main
        movl    $12, -4(%ebp)         ;*****
        movl    $0, %eax
        leave
        ret

الشيء ذو الصلة ملحوظ ;***** ويمكنك أن ترى أن القيمة يتم إنشاؤها بواسطة المحول البرمجي وإدراجها مباشرة في mov اكتب التعليمات.

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

بالنسبة إلى كيفية حساب المترجم ما يجب أن تكون القيمة، فإن الأمر يتعلق بتقييم التعبير وهو سؤال آخر صحيح :-)

  • يتم حساب نتيجة الحساب في RHS (الجانب الأيمن) من قبل المحول البرمجي في خطوة تسمى "الانتشار المستمر".
  • ثم، يتم تخزينها كمعامل لتعليمات التجمع تتحرك القيمة في a

إليك تفكيك من MSVC:

  int a;
  a = 10 + 5 - 3;

0041338E  mov         dword ptr [a],0Ch 

يستند سؤالك إلى فرضية غير صحيحة.

خاصية تحديد lvalue. في ج هو أنه يحتوي على مكان في التخزين، أي أنه هو مخزن. وبعد هذا هو ما يميز lvalue من rvalue.. وبعد rvalue هو ليس تخزينها في أي مكان. هذا ما يجعله rvalue. إذا تم تخزينها، فستكون كذلك lvalue. حسب التعريف.

يتم استخدام مصطلحات "Lvalue" و "RValue" لإثارة عالم التعبيرات. إنه، (10+5-3) هو تعبير يحدث أن يكون RVALUE (نظرا لأنك لا تستطيع تطبيق ومشغله - في C ++ القواعد أكثر تعقيدا). عند وقت التشغيل، لا توجد تعبيرات أو LVALUES أو RVALUES. على وجه الخصوص، لا تخزينوا في أي مكان.

كنت تتساءل أين تم تخزين القيمة 12، ولكن القيمة 12 ليست lvalue ولا rvalue (بدلا من التعبير 12 التي ستكون rvalue، ولكن 12 لا يظهر في البرنامج الخاص بك).

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