الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ما تقسيركم لهذا التصرف .

بدأه ofnet في 3 أبريل 2010 · 26 رد · 2,304 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم .

إلى خبراء السي++ ، بالنسبة لمعاملات الزيادة القبلية ، ما تفسيركم لهذا التصرف ؟

int a = 5;
cout << ++a << ++a << ++a;

نتيحة ٍVisual c++ كانت :

888

أما Dev c++ كانت :

678

النتائج كانت مختلفة بين Dev c++ و Visual c++.

صحيح أن معامل الزيادة القبلية له أسبقية التنفيذ!

أنا أعلم أنا Dev c++ يستعمل مترجم GCC و أنه يمكن تغيير مستويات الترجمة ، لكن ليس لهذه الدرجة.

يا ترى من هو المحق :haha: ؟

تم تعديل هذه المشاركة بواسطة ofnet في 3 أبريل 2010 في 14:22

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#2

السلام عليكم

من حلال النتيجة المحق هو Dev C++

لدينا في البداية a=5

اذن سيتم زيادة العدد 5 ب1 كل مرة وستكون النتائج : 6 ,7 ثم 8.

المرحلة 1: a=5+1 ->6

المرحلة 2: a=6+1->7

المرحلة 3: a=7+1->8

تم تعديل هذه المشاركة بواسطة xpero في 3 أبريل 2010 في 14:53

#3

حسب الكود فإن ال Dev c++ محق و ال visual مخطيء

وذلك بسبب أن visual c++ يستخدم مبدأ آخر عملية هي التي تخرج أولا، لذلك فإن آخر عملية عنده هي 8 وبذلك فإنه يعطي قيمة ال 8 إلى a مباشرة وتصبح 888.

ولكن إن كتبنا في ال visual c++ هكذا:

int a=5;
cout<<++a;
cout<<++a;
cout<<++a;

فإن ال visual و ال dev لهما نفس النتيجة 678.

#4

هل هذا يعني ترك Visual C++

تم تعديل هذه المشاركة بواسطة ofnet في 3 أبريل 2010 في 15:08

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#5

الدالة cout تعمل من اليمين لليسار .

أي ان ناتج الدالة يجب ان يكون :

876

وليس

678

ولكن الغريب في هذه الجملة في الدوت نت اظهرت ناتج معاكس تماما

 cout<<a++<<++a<<a++;

ففي dev اظهرت

775

بينما في الدوت نت اظهرت الناتج ( مما يؤكد بدئها من اليمين ولكن كيف اصبح الرقم الاوسط 8 ) ؟؟؟

785

تحياتي

2

OMANI FOR EVER

-------------------------------------------------

post-12787-12780191801974.jpg

-------------------------------------------------

#6
omani كتب:

الدالة cout تعمل من اليمين لليسار .

كيف ذلك أخي؟:blink:

لوكانت الدالة cout تعمل من اليمين لليسار لمذا نضع endl في الاخير :cool:

#7
اقتباس
يا ترى من هو المحق

أرى أن الحق بجانب المترجم dev مع عدم قدرتي على تفسير النتيجة التي أظهرها المترجم العملاق visual

اقتباس
السلام عليكم

من حلال النتيجة المحق هو Dev C++

لدينا في البداية a=5

اذن سيتم زيادة العدد 5 ب1 كل مرة وستكون النتائج : 6 ,7 ثم 8.

المرحلة 1: a=5+1 ->6

المرحلة 2: a=6+1->7

المرحلة 3: a=7+1->8

أوافقك الرأي .. هذه هي النتيجة اليت كنت أتوقع.

اقتباس
هل هذا يعني ترك Visual C++

أبدا أبدا .. يا أخي الكريم !!! المترجم visual يُعتبر من أضخم مترجمات لغة السي++ وقد صُمم من طرف شركة "مايكروسوفت" , يعني مستحيل يغلط في أشياء كهذه .. لا بد من وجود تفسير منطقي للنتيجة المُظهرة .. وهذا ما ننتظره من خبراء القسم.

دمتم بود.

#8

شكرا عل التجاوب ، لكن هل هذا يعني أن أتخلى عن Visual C ؟

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#9

يا جماعة كتابة أي كود يجب أن يكون له نفس النتيجة عندما نغير الطريقة من:

int a = 5;
cout << a++ << ++a << a++;

إلى:

int a=5;
cout<<a++;
cout<<++a;
cout<<a++;

لذلك فإن حالة ال dev c++ لا يغير أسلوبه بينما ال visual يغير أسلوبه ويكتب نفس نتيجة ال dev c++ في الحالة الثانية.

لذلك فإننا نعتبر ال dev c++ محق و visual c++ مخطيء.

#10
أحمد المتألق كتب:

أرى أن الحق بجانب المترجم dev مع عدم قدرتي على تفسير النتيجة التي أظهرها المترجم العملاق visual

أوافقك الرأي .. هذه هي النتيجة اليت كنت أتوقع.

أبدا أبدا .. يا أخي الكريم !!! المترجم visual يُعتبر من أضخم مترجمات لغة السي++ وقد صُمم من طرف شركة "مايكروسوفت" , يعني مستحيل يغلط في أشياء كهذه .. لا بد من وجود تفسير منطقي للنتيجة المُظهرة .. وهذا ما ننتظره من خبراء القسم.

دمتم بود.

لكن أضن أن نتيجة مترجم visual c++ القديم كانت نفس مترجم Dev C++

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#11
xpero كتب:

كيف ذلك أخي؟:blink:

لوكانت الدالة cout تعمل من اليمين لليسار لمذا نضع endl في الاخير :cool:

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

cout<<a++<<++a<<a++;

هرعت لمايكروسوفت أستفسر عن السبب . وانتظر الشرح هناك .

http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/0bb2f44d-200e-48f3-bdc8-1837916049fc

تحياتي

1

OMANI FOR EVER

-------------------------------------------------

post-12787-12780191801974.jpg

-------------------------------------------------

#12
اقتباس
ذلك فإن حالة ال dev c++ لا يغير أسلوبه بينما ال visual يغير أسلوبه ويكتب نفس نتيجة ال dev c++ في الحالة الثانية.

لذلك فإننا نعتبر ال dev c++ محق و visual c++ مخطيء.

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

المترجم visual (كما قلت سابقا) مُصمم على يد أمهر المبرمجين في العالم .. إذْ لا يمكنه أن يخطئ في أشياء بسيطة كهذه .. يعني إذا لم تستطع تفسير النتيجة فلا داعي للتجريح !!

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

أطيب الأمنيات

1
#13

يالها من مصيبة :huh:

الحمد لله أنني أتعامل من قديم الزمان مع ال Dev c++ :cool:

#14
أحمد المتألق كتب:

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

المترجم visual (كما قلت سابقا) مُصمم على يد أمهر المبرمجين في العالم .. إذْ لا يمكنه أن يخطئ في أشياء بسيطة كهذه .. يعني إذا لم تستطع تفسير النتيجة فلا داعي للتجريح !!

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

أطيب الأمنيات

يا أخي نحن لم نشكك يوما في Microsoft أردنا تفسيرا فقط ! :cool:

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#15

أحمد المتألق

اخي لا تتق بامهر المبرمجين في العالم ..كل شخص يمكنه ان يخطئ ,الكمال لله.

نحن لا يهمنا طرقة العمل بقدر ماتهمنا النتيجة. وكما راينا فنتيجة gcc كانت منطقية و وواضحة ويمكننا التنبؤ بها حتى دون تجريب الكود بينهما نتيجة visual cpp غير واضحة ..

1+2=3 و 2+1 =3 نحصل على نفس النتيجة كيفما كانت طريقة حسابها..المهم هو النتيجة.

#16

ربما توصلت الى تفسير ..هو ان visual cpp يقوم بالعمل على نسخة من المتغير a وليس a نفسه.

جربو الكود التالي وستحصلون على نفس نتيجة visual cpp


#include <iostream>

int main(int argc, char *argv[])
{
int a =5;
int y=a;
std::cout<<++y<<++y<<++y;
std::cin>>a;
return 0;
}

ربما هناك اختلاف في تمرير البرامترات للدالة (بالقيمة لفجوال سي++ و بالمرجع ل ج س س)

تم تعديل هذه المشاركة بواسطة xpero في 3 أبريل 2010 في 16:10

#17
xpero كتب:

ربما توصلت الى تفسير ..هو ان visual cpp يقوم بالعمل على نسخة من المتغير a وليس a نفسه.

جربو الكود التالي وستحصلون على نفس نتيجة visual cpp


#include <iostream>

int main(int argc, char *argv[])
{
int a =5;
int y=a;
std::cout<<++y<<++y<<++y;
std::cin>>a;
return 0;
}

ربما هناك اختلاف في تمرير البرامترات للدالة (بالقيمة لفجوال سي++ و بالمرجع ل ج س س)

لا تغيير نفس النتائج السابقة

الفجيوال 888 والديف 876

OMANI FOR EVER

-------------------------------------------------

post-12787-12780191801974.jpg

-------------------------------------------------

#18

إلى الأخ xpero

بقت نفس الحالة 888.

#19

ممم هذا محير..لقد ترجمت الكود في ال Qt

وفي الاول حصلت على :8-7-6

وبعد اضافة المتغير y حصلت على 8-8-8

:wacko:

03042010133949.png

تم تعديل هذه المشاركة بواسطة xpero في 3 أبريل 2010 في 17:01

#20

السلام عليكم ...

هذا الأمر خاطئ من ناحية الـ Semantics الخاصة بـ ++C و C.

كل ما في الأمر, أنه Undefined Behavior لأنك تقوم بتعديل قيمة متغير أكثر من مرة خلال Sequence Point واحدة.

باختصار الأمر خاطئ, و لا يوجد مترجم صحيح و الآخر خاطئ لأن الكود نفسه خاطئ.

في C و ++C ليس كل شيء خاطئ يعطى Syntax Error, لأنك لو تلاحظ ليس هناك خطأ لغوي.

حاول الإطلاع على معنى الـ Undefined Behavior في الـ Cpp Standards.

تحياتي...

3
#21

Khaled.Alshaya

نعم اخي هناك undefined operation على المتغير a.

تم تعديل هذه المشاركة بواسطة xpero في 3 أبريل 2010 في 17:01

#22

إلى الأخ Khaled.Alshaya

ممكن رابط إلى Undefined behavior في الـ Cpp Standards

#23
اقتباس
ممكن رابط إلى Undefined behavior في الـ Cpp Standards

للأسف تحتاج إلى شرائها, أو الذهاب للموضوع المثبت للأخ محمد الذي وضع فيه كل الـ Standards الخاصة بـ C و ++C لتحميلها من هناك:)

عموماً, هذه إجابة كنت قد أجبتها منذ فترة في SO حول الموضوع. و ستجد في الإجابة التي تعلو إجابتي طلبك. أنا قمت بشرح الموضوع بطريقة مبسطة, بينما الـ Standards تعرفها بشكل صارم لمنع حصول إشكال, لذلك قد تجد الـ Standards غير مفهومة

إن لم تكن لديك خلفية حول الموضوع.

ابحث في SO حول Undefined Behavior و ستجد الكثير,

تحياتي....

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 3 أبريل 2010 في 17:29

#24
Khaled.Alshaya كتب:

السلام عليكم ...

هذا الأمر خاطئ من ناحية الـ Semantics الخاصة بـ ++C و C.

كل ما في الأمر, أنه Undefined Behavior لأنك تقوم بتعديل قيمة متغير أكثر من مرة خلال Sequence Point واحدة.

باختصار الأمر خاطئ, و لا يوجد مترجم صحيح و الآخر خاطئ لأن الكود نفسه خاطئ.

في C و ++C ليس كل شيء خاطئ يعطى Syntax Error, لأنك لو تلاحظ ليس هناك خطأ لغوي.

حاول الإطلاع على معنى الـ Undefined Behavior في الـ Cpp Standards.

تحياتي...

إذا أنت تعني أن هذا التعبير خاطيء أو بالأحرى لا يجب استعمال هذا التعبير ، على العموم بوركت أخي Khaled.Alshaya طلعت انت أحسن من مترحم Microsoft :blush:

تم تعديل هذه المشاركة بواسطة ofnet في 3 أبريل 2010 في 22:16

لا خيــــــــــر في كاتــــــــــم العلــــــــــم

سأل الممكن المستحيل ، قال أين تسكن ، فال أسكن في عقول العاجزين

#25

يا أخ ofnet,

في لغة C و ++C, يمكن للمبرمج أن يقوم بكتابة كود غير صحيح بكل بساطة, و ربما "يعمل" ذلك الكود, و لكن نتيجته لن تكون "محددة" دائماً.

عندما تقوم بأي Undefined Behavior فأنت دخلت منطقة ضبابية, منذ تلك اللحظة البرنامج خاطئ و إن أعطى الإجابة الصحيحة.

تخيل أنك تقوم بالتالي:

int* addr = /* some random address */;
std::cout << *addr;

ما تراه عبارة عن Undefined Behavior, لأنك قمت بالوصول إلى ذاكرة لا تملكها. بالطبع في C و ++C لن يأتي أحد و يخبرك بأنك قمت بهذا الأمر, ببساطة ليس هناك run-time checking.

بمجرد محاولتك الوصول إلى ذلك المكان الذي يشير إليه addr فإن برنامجك دخل منطقة ضبابية, النتائج يمكن أن تكون أي شيء!

الآن يمكن أن نرجع للمثال الذي وضعته :)

في C و ++C (في الحقيقة هما لغتان مختلفتان, و قواعدهما مختلفة في كثير من الأحيان, و لكن للتبسيط لا أكثر).

فإننا عندما ندخل إلى statement فإن المترجم سيقوم بإحضار قيم المتغيرات الموجود في تلك الـ Statement. و هذه اللحظة تسمى Sequence Point, في حالتنا هذه سيقوم بإحضار a

كما ترى, فإن a عندما تم إحضارها كانت قيمتها تساوي 5, ثم قمنا بالزيادة عليها بمقدار 1

طبعاً لا مشكلة حتى الآن, لأننا لو انتظرنا حتى نصل إلى الـ Sequence Point التالية, بحيث يتم إعادة a إلى مكانها لمن يريد الاستعلام عنها من جديد.

و لكن الذي حصل, هو أننا قمنا بزيادة a مرة أخرى.

في هذه المرة الثانية, أين حصلت الزيادة بالضبط؟!

هل في a التي أحضرناها, أو في a الأصلية؟

هنا المشكلة. في لغة C و ++C لا يمكنك تعديل متغير أكثر من مرة واحدة بين two Sequence Points متتالية.

بالطبع, كل مترجم حر أن يتصرف بالطريقة التي تعجبه, لأن الكود ليس صحيح أصلاً.(و لكن تذكر أنه ليس Syntax Error حتى يخبرك المترجم).

هناك لغات, يتم تحديد معنى إحضار و إعادة a فيها, و يتم حل هذه المشكلة في تعريف اللغة نفسه. لا أعرف الكثير عن Java, و لكن حسبما أعرف ليس هناك Undefined Behavior فيها.

طبعاً, سيطرأ سؤال مباشرة, و هو لماذا C و ++C لا تقومان بتعريف معنى إحضار a و إعادتها؟!

الجواب, هو أن C و ++C تجبران المبرمج على عدم فعل ما تكلمنا عنه, و لكن في نفس الوقت, فهي تعطي المترجم حرية أكبر بكثير لفعل ما يريده.

فربما يحضر المتغير إلى register, و هو الغالب, و في هذه الحالة يصبح هناك نسختان, و ربما يقوم بعمليات Optimization أخرى.

المهم هو أننا طالما التزمنا بقوانين اللغة (و هي صعبة بالفعل), فإن المترجم سيعطينا الإجابة الصحيحة.

عدا عن ذلك, فلا معنى للإجابة, لأن السؤال خاطئ في الأصل.

تحياتي....

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 4 أبريل 2010 في 04:50

4

مواضيع مشابهة