سؤال

في ج، لا يمكننا استخدام وعن عنوان متغير التسجيل ولكن في C ++ يمكننا أن نفعل نفس الشيء. لماذا هو قانونية في C ++ ولكن ليس في ج؟ يمكن لشخص يرجى توضيح هذا المفهوم متعمقا.

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

المحلول

إليك مقتطف من القسم 6.7.1 (حاشية 101) من C99 Standard (PDF):

قد يعامل التنفيذ أي register إعلان ببساطة باعتباره auto إعلان. ومع ذلك، لا يمكن استخدام وحدة التخزين المعونة أو لا يمكن استخدام عنوان أي جزء من كائن معلن مع سجل محدد من فئة التخزين, ، إما صراحة (عن طريق استخدام UNARY & المشغل كما هو الذي تمت مناقشته في 6.5.3.2) أو ضمنا (عن طريق تحويل اسم صفيف إلى مؤشر كما تمت مناقشته في 6.3.2.1). وبالتالي، فإن المشغل الوحيد الذي يمكن تطبيقه على صفيف معلن مع محدد فئة التخزين register يكون sizeof.

ومن القسم 7.1.1، الفقرة 3 من C ++ Standard (PDF):

أ register محدد لديه نفس دلالات auto المواصفات مع تلميح إلى تنفيذ أن الكائن المعلن حتى يتم استخدامه بشكل كبير. ملاحظة: يمكن تجاهل التلميح وفي معظم التطبيقات سيتم تجاهلها إذا تم اتخاذ عنوان الكائن. - ملاحظة

الحكايات المرح حول register

المجموعة C ++ (WG21) يريد أن ينتقد register:

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

ملاحظات من مارس 2009 الاجتماع:

وكان إجماع CWG لصالح الانتقاص register.

انظروا إلى ما مجموعة C99 (WG14) قال حول register (بي دي إف) في اجتماع:

اتفاق عام لإنفاق "autoالكلمة الرئيسية. يجب أن نسأل WG21 للعودة إلى الاستخدام السابق ل "register"(لا يوجد عنوان)؟ لا، هذا لن يطير مع WG21.

نصائح أخرى

الكلمة الأساسية السجل هي تلميح فقط ويمكن تجاهلها. تجاهل معظم مترجم C ++ كل الوقت، لكن أي مترجم C ++ سوف يتجاهله إذا كنت تأخذ عنوان المتغير، أو إنشاء مرجع لذلك.

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

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

الجزء ذو الصلة من معيار C ++ هو 7.1.1.3:

يحتوي محدد المسجل على نفس الدلالات كمحاسب تلقائية جنبا إلى جنب مع تلميح إلى التنفيذ الذي سيتم استخدامه الكائن الذي تم إعلانه بشدة. [ملاحظة: يمكن تجاهل التلميح وفي معظم التطبيقات سيتم تجاهلها إذا تم اتخاذ عنوان الكائن. - ملاحظة

آسف للإجابة المتأخرة للغاية.

المشكلة هي أنه في ج، register يعني في الأصل تخزين القيم في سجل وهذا هو السبب فقط int و char يمكن استخدامها لذلك. ولكن مع مرور الوقت وخاصة C ++ القياسية، وسعت "الوصول السريع" بدلا من "في سجل وحدة المعالجة المركزية". لذلك في C ++، صفيف ربما register اكتب ولكننا نعلم أنه من الممكن تخزين صفائف في سجل وحدة المعالجة المركزية. وبالتالي، من المنطق المنطقي معالجة سجل C ++ (بالمعنى أعلاه)، ولكنه سيظل أي معنى إذا كانت القيم في سجل وحدة المعالجة المركزية في الواقع.

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

لأن وظائف الأعضاء تتطلب ضمنيا this المعلمة، سيكون من المستحيل الاتصال بهم من كائن أعلن register. وبعد في ج، لا يوجد شيء يحظرك من القول register struct X x;, ، لذلك يجب السماح به هذه اللغة في C ++ [نظرا لأن التوافق C هو السبب الفردي موجود باللغة الرئيسية]. ولكن إذا حظرت استدعاء وظائف الأعضاء وكذلك أخذ العناوين، فإن ذلك يغطي أيضا مكالمة البناء الأولي. في جوهرها، لن يعمل على أنواع غير جراب. لذلك في نهاية المطاف مع محدد فئة تخزين واحدة صالحة فقط لمجموعة فرعية صغيرة من الأنواع القانونية، عندما يمكن استخدام كل البقية لأي شيء.

يمكنك أيضا إنشاء مراجع إلى هذه الأشياء، على الرغم من ذلك، من الناحية الفنية، لا يتعين على المترجم معالجة المراجع كمؤشرات. register int i; int& x; ليس مطلوبا للحصول على مساحة لمتغيرين، ولكن إذا قمت بذلك لاحقا &x ينتهي بك الأمر مع مؤشر ل i. وبعد لذلك يجب تقديم البنى الأولي غير قانوني. على الرغم من أن هذا يبدو وكأنه مشكلة غير موجودة، نظرا لأن المراجع غير موجودة في ج، فإنها تعود إلى النقاط السابقة لدينا، حسب register لم يعد من الممكن نسخ المواصفات. منشئ نسخة محمول المترجم هو من النموذج X::X(const X&) أو X::X(X&) حسب الاقتضاء.

لذلك، من أجل الحفاظ على توافق ج، لديهم لجعل register فريد من نوعه كمحدد فئة تخزين في أنه لا ينطبق على جميع الأنواع، وتعديل جزءين مختلفين على الأقل من المعيار في مكان آخر [لتحديد أنه لا يمكنك إنشاء مرجع إلى متغير معلن مع register المواصفات، وإلى بطريقة ما تعمل حول المراجع للحصول على نسخ بود]. أو، يمكنهم فقط أن يقولوا "حسنا لإجراء العنوان" والسماح للمجمعات أن يقرروا ما إذا كانوا يكرمون الطلبات أم لا. شيء كانوا يخططون للقيام بأي حال.

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

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

الشيء المهم أن نتذكر هو أن "التسجيل" هو مجرد تلميح للمترجم (واحد غير مرغوف به في ذلك؛ لم أر أي تحسن في السرعة، وربما تجاهل معظم المجمعين فقط). يسمح كلاهما C و C ++ بتجاهل "نصيحة" الخاصة بك والحفاظ على المتغير في الذاكرة. بالطبع، إذا كنت تأخذ عنوان المتغير، فسوف يجبره على تعيين بقعة في الذاكرة.

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

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

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

C و C ++ هما لغتين مختلفة، مع مجموعة فرعية كبيرة مشتركة. لهذا السبب تختلف بعض الأشياء بينهما.

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

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

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

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