سؤال

في C.1.3 من C++ IS (2003.إنه موجود في C++ 11 IS أيضًا)، يشير المعيار إلى اختلاف بين ISO C وC++؛وهي ل

char arr[100];

sizeof(0, arr) عائدات sizeof(char*) في ج، ولكن 100 في سي ++.

لا أستطيع العثور على أي وثائق ل sizeof أخذ حجتين.البديل الواضح هو عامل الفاصلة، لكنني لا أعتقد ذلك: sizeof(arr) في C هو 100; sizeof(0, arr) يكون sizeof(char*).كلاهما sizeof(0, arr) و sizeof(arr) نكون 100 في سي ++.

ربما أفتقد المغزى الكامل لتنظيم الدولة الإسلامية في هذا السياق.هل أستطيع مساعدتك؟هذا مشابه لسؤال تمت مناقشته في عام 2009، لكن لم يشر أحد إلى تنظيم الدولة الإسلامية، ولا أعتقد أنه تم تقديم الإجابة الصحيحة.


يحرر:في الواقع، يتحدث تنظيم الدولة الإسلامية عن عامل الفاصلة.لذلك، لسبب ما (0, arr) يعود أ char* في C، ولكن أ char[100] في سي ++.لماذا؟

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

المحلول

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

نصائح أخرى

في لغة C، لا يُنتج عامل الفاصلة قيمة، وبالتالي المصفوفة arr وهي قيمة يتحلل إلى نوع المؤشر وهو rvalue (في هذه الحالة).لذا sizeof(0,arr) يصبح يعادل sizeof(char*), ، بسبب lvalue إلى rvalue تحويل.

لكن في C++، يُنتج عامل الفاصلة قيمة lvalue.لا يوجد lvalue إلى rvalue تحويل.لذا sizeof(0,arr) يبقى كما هو، وهو ما يعادل sizeof(char[100]).

بالمناسبة، sizeof ليست وظيفة، انها عامل التشغيل.لذا فإن ما يلي صحيح تمامًا لـ C++ (و C، إذا كنت تتخيل printf بدلاً من cout):

int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;

العرض التوضيحي : http://www.ideone.com/CtEhn

قد تعتقد أنني قمت بتمرير 4 معاملات إلى sizeof ولكن هذا خطأ. sizeof يعمل على النتائج من عوامل الفاصلة.وبسبب وجود العديد من عوامل الفواصل ترى العديد من المعاملات.

4 معاملات مع 3 عوامل تشغيل فاصلة؛تماما كما هو الحال في 1+2+3+4, ، هناك 3 عوامل، 4 معاملات.

ما ورد أعلاه يعادل ما يلي (صالح في C++ 0x):

auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result

العرض التوضيحي : http://www.ideone.com/07VNf

إذن فهو فاصلة المشغل الذي يجعلك يشعر أن هناك الكثير الحجج.هنا فاصلة عامل تشغيل، ولكن في استدعاء الوظيفة، فاصلة ليس عامل تشغيل، إنه مجرد فاصل وسيطة.

function(a,b,c,d); //here comma acts a separator, not operator.

لذا sizeof(a,b,c,d) يعمل على يكتب من نتيجة , المشغلين بنفس الطريقة بالضبط sizeof(1+2+3+4) يعمل على يكتب من نتيجة + العاملين.

لاحظ أيضًا أنك لا تستطيع يكتب sizeof(int, char, short), ، على وجه التحديد بسبب فاصلة لا يمكن للمشغل أن يعمل أنواع.تعمل على قيمة فقط.أظن، sizeof هو العامل الوحيد في C وC++ الذي يمكن العمل عليه أنواع أيضًا.في C++، هناك عامل آخر يمكن أن يعمل عليه أنواع.اسمها typeid.

إنه عامل فاصلة.والفرق الذي تتحدث عنه ليس له أي علاقة على الإطلاق sizeof.يكمن الاختلاف حقًا في سلوكيات lvalue-to-rvalue وray-to-pointer وسلوكيات الاضمحلال المشابهة بين لغات C وC++.

لغة C هي إلى حد ما سعيدة في هذا الصدد:تتحلل المصفوفات إلى مؤشرات على الفور تقريبًا (باستثناء عدد قليل جدًا من السياقات المحددة)، وهذا هو سبب ظهور نتيجة 0, arr التعبير لديه char * يكتب.وهو ما يعادل 0, (char *) arr.

في لغة C++، تحافظ المصفوفات على "الصفيف" لفترة أطول.عندما تستخدم في سياق , لا تتحلل صفائف المشغل إلى مؤشرات (ولا تتحلل القيم l إلى قيم r)، وهذا هو السبب في أن نوع C++ 0, arr التعبير لا يزال char[100].

وهذا ما يفسر الفرق في sizeof السلوك في هذا المثال. ?: المشغل هو مثال آخر للمشغل الذي يوضح الفرق المماثل في سلوك الاضمحلال، أي. sizeof(0 ? arr : arr) سيعطيك نتائج مختلفة في C وC++.في الأساس، كل هذا ينبع من حقيقة أن مشغلي لغة C لا يحافظون عادةً على قيمة معاملاتهم.يمكن استخدام الكثير من العوامل لتوضيح هذا السلوك.

هذا ليس sizeof أخذ حجتين. sizeof هو عامل، وليس وظيفة.

اعتبر ذلك (0, arr) هو تعبير يستخدم عامل الفاصلة، وكل شيء آخر يقع في مكانه الصحيح.

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

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

أفضل طريقة لمعرفة ما يمكن أن يحدث هنا هو إلقاء نظرة على القواعد في المعيار.إذا نظرنا إلى مسودة القسم القياسي C99 6.5.3 المشغلين الأحاديين فقرة 1 يمكننا أن نرى أن القواعد النحوية لـ sizeof هي:

sizeof unary-expression
sizeof ( type-name )

لذا فإن الخيار الثاني لا ينطبق ولكن كيف sizeof unary-expression تنطبق في هذه الحالة؟إذا نظرنا إلى القسم A.2.1 التعبيرات من مسودة المعيار والعمل من خلال القواعد كما يلي:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

نحصل على الأقواس حول تعبير والآن علينا فقط أن ننظر إلى قواعد اللغة مشغل الفاصلة من القسم 6.5.17 مشغل الفاصلة ونحن نرى:

expression:
  assignment-expression
  expression , assignment-expression

إذن لدينا الآن:

sizeof( expression , assignment-expression )
                   ^
                   |
                   comma operator

كلاهما تعبير و تعبير المهمة يمكن أن يأخذنا إلى التعبير الأساسي والذي يحتوي على القواعد النحوية التالية:

primary-expression:
  identifier
  constant
  string-literal
  ( expression )

و 0 هو ثابت و arr هو معرف اذا لدينا:

 sizeof( constant , identifier )

إذن ماذا يفعل مشغل الفاصلة إفعلها هنا؟قسم 6.5.17 فقرة 2 يقول:

يتم تقييم المعامل الأيسر لمشغل الفاصلة كتعبير فارغ؛هناك نقطة تسلسل بعد تقييمها.ثم يتم تقييم المعامل الصحيح؛فالنتيجة لها نوعها وقيمتها.97)

نظرًا لأن عامل الفاصلة ليس أحد الاستثناءات التي لا يتم فيها تحويل المصفوفة إلى مؤشر، فإنه ينتج مؤشرًا (تم تناول هذا في القسم 6.3.2.1 القيم والمصفوفات ومحددات الوظائف) مما يعني أننا في نهاية المطاف مع:

sizeof( char * )

في سي ++ القواعد متشابهة إلى حد كبير لذا ننتهي في نفس المكان ولكن عوامل الفاصلة تعمل بشكل مختلف.القسم القياسي لمسودة C++ 5.18 مشغل الفاصلة يقول:

[...]نوع وقيمة النتيجة هما نوع وقيمة المعامل الصحيح؛والنتيجة هي من نفس فئة القيمة مثل المعامل الصحيح[...]

هكذا و صفيف إلى المؤشر التحويل غير مطلوب ولذا ننتهي بـ:

sizeof( char[100] ) 

كما قال العديد من قبل ، وأريد إضافة شيء واحد فقط ، sizeof هو عامل يأخذ إما تعبيرًا أو تعبيرًا. لهذا السبب اعتدت أن أكتب أقواسًا بحجم فقط إذا كان تعبيرًا مُلقى. Genacodicetagpre

سأكتب Genacodicetagpre

لكن Genacodicetagpre

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

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