کامپایلر C++ ترتیب عملگرها را چگونه بررسی می‌کند؟

چرا جواب 6میشه؟ توضیح رو اگر بدید ممنون میشم

2 Likes

اول a رو برابر 2 قرار داده
بعد b رو در a که یه واحد بهش اضافه شده ضرب کرده که میشه 6

عملگر post increment مقدار رو یکی اضافه می‌کنه اما خروجی آن مقدار اولیه هست. با توجه به این و تقدم عملگرها خودتان باید بتوانید توضیح دهید. در اینجا تساوی اخرین تقدم را دارد.
بعد از آن سعی کنید پاسخ عبارات زیر را حدس زده و توضیح دهید.

int a=2, b;
b = a * a * a++;

int a=2, b;
b = (a + 1) * a++;

2 Likes

خیلی ممنون از راهنماییتون، پاسخ اولی 18میشه و تو دومی چون پرانتز تقدم داره اول باید aرو که 2هست با 1جمع کرد که 3میشه بعد حاصل رو در ++a که خروجیش همون 2هست ضرب کرد که میشه6؟

در مورد اولی ترتیب ضرب از چپ به راست هست، بنابراین معادل عبارت زیر هست:

b = (a * a) * a++

که نتیجه‌اش ۱۸ نیست.

ببخشید مگه ترتیب تقدم اول پرانتز نیست و بعد ++ و بعد ، اینجا که تو خود مثال پرانتز نیومده، پس چرا اینکه اول ++رو اثر بدم اشتباه میشه که یعنی بشه
2
3*3

سوال خیلی خوبیه.
در ابتدا باید بگم که توضیحات قبلی من ایراد داشت چون بر اساس استاندارد C++ نتیجه تمام مثال‌های بالا نامعین است.

دو مفهوم وجود داره: تقدم عملگرها operator precedence و ترتیب بررسی (یا ارزیابی) order of evaluation
این دو با هم دیگه فرق دارن.
عملگری که تقدم بالاتری داره الزاما اول اجرا نمی‌شود بلکه با عملوندهایی که بلافاصله کنارش هستند تشکیل یک عبارت را می‌دهد، به گونه‌ای که انگار خود و عملوندهایش درون یک پرانتر قرار گرفته‌اند. تقدم عملگرها در زمان کامپایل کاملا مشخص می‌شود.
ترتیب بررسی، ترتیب اجرای عملیات‌ها در زمان اجرا runtime است و عموما به جز چند مورد مشخص در استاندارد تعریف نشده است. وقتی چیزی در استاندارد تعریف نمی‌شود هر ترکیب سخت‌افزاری و نرم‌افزاری می‌تواند بر اساس سلیقه خود عمل کند. این آزادی عمل می‌تواند به افزایش سرعت برنامه‌ها کمک کند.
در حین بررسی برنامه ابتدا سعی می‌کند نتیجه عبارت کلی را به دست آورد. در عملگرهایی که دو عملوند دارند، این که اول عملوند راست بررسی شود یا چپ، تعریف نشده و حتی می‌تواند به صورت موازی اجرا شود. همچنین ترتیب بررسی آرگومان‌ها در توابعی که چند آرگومان دارند تعریف نشده.

برای مثال از نظر تقدم عملگرها عبارت

b = a * a++

معادل

b = (a * (a++))

است. در حین بررسی کامپایلر ابتدا کل عبارت را در نظر می‌گیرد. برای تعیین نتیجه آن عملگر تساوی و عملوندهایش را بررسی می‌کند. در حین بررسی عملوند راست، باید صرب را بررسی کند. در اینجا مختار است اول عملوند راست یا چپ را بررسی کند (یا حتی موازی بررسی کند). اگر اول عملوند چپ را بررسی کند نتیجه متفاوت است.

البته آزادی عمل کامپایلر در ترتیب بررسی خیلی بیش از این است. در اینجا می‌توانید موارد استثنا را ببینید.
https://en.cppreference.com/w/cpp/language/eval_order
چند مثال مشابه از موارد تعریف نشده هم آمده است.

پی‌نوشت اگر هشدارهای کامپایل فعال باشد با اکثر کامپایلرها برای موارد بالا هشدار sequence point دریافت می‌کنید.
زبان C++ قابلیت‌های زیادی دارد که با خودشان پیچیدگی هم می‌آورند. سعی کنید همیشه همه هشدارها را فعال و بررسی کنید یا فقط در موارد اطمینان از آن‌ها استفاده کنید.

3 Likes

خیلی ممنون از راهنماییتون