LINUX.ORG.RU

Порядок вычисления выражения в msvc c++

 


0

4

Доброго дня всем. Понимаю, что компил оффтопик, но всё же. Пусть у нас есть выражение a = foo() + bar();

Известно, что стандарт плюсов не регулирует, какая функция выполниться раньше - порядок вычисления тут неопределён.

Но мне сказали, что именно в компиле вижлы считается слева направо и нет никакой неопределенности. Так ли это?

Ответ на: комментарий от zamazan4ik

Меня просто интересует, определён порядок или нет.

В MSVC – без понятия, в стандарте – нет.

Stil ★★★★★
()

А если результат bar() был нужен раньше и компилятор может доказать, что он не изменится?

anonymous
()
Ответ на: комментарий от Stil
#include "iostream"

double x;
double  foo () {
   x*=x+2; return x;}
   
double  bar () {
    x*=x*x+2; return x;}

int main() {
x=2;
         
double a = bar() + foo();
 
std:: cout << x << "\t" << a << std::endl;

x=2;
double b = foo() + bar();
std:: cout << x << "\t" << b << std::endl;
}
g++ temp.cpp -o temp && ./temp
168     180
528     536

вот это хотел сказать...

rgB
()
Ответ на: комментарий от rgB

вот это хотел сказать...

зависит от того как реализован operator::+ , как член класса или как friend. С++ он такой :-)

Чтоб разночтений не было даже в теории, для всех friend operator::xxx надо ставить __pascal__ что апологетов плюсов вводит в батхёрд :-)

MKuznetsov ★★★★★
()

Но мне сказали, что именно в компиле вижлы считается слева направо и нет никакой неопределенности.

Не видел такого дока у студийного компиля. Но это UB и даже на авось лучше не делать, а то потом привыкнешь и будут на тебя пальцем тыкать

anonymous
()
Ответ на: комментарий от slovazap

Объясняю - я хочу выяснить, правда это или нет. Вдруг это есть в спецификации компила вижлы? Источник вопроса - бред препода из университета

zamazan4ik ★★
() автор топика
Ответ на: комментарий от anonymous

По стандарту это чистой воды ub, спору нет. А меня интересует именно компил вижлы

zamazan4ik ★★
() автор топика
Ответ на: комментарий от zamazan4ik

Так у него и спроси. Пусть покажет конкретное место в спецификации, а сам ткни его мордой в стандарт. Я думаю он просто скомпилил и подумал что тот порядок что у него получился что-то значит. А так-то тут про спецификацию мсявого недокомпилера спрашивать самое место.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Я его мордой в стандарт на лекции ткнул. Но он выкрутился, сказав, что имел в виду спецификацию компила вижлы, а спецификацию не показал он мне этого самого компила. Вот и хочу добиться я правды.

zamazan4ik ★★
() автор топика
Ответ на: комментарий от zamazan4ik

ну так давно бы уже скачал бы windows 10 evalution for developers и накатил бы все это в virtualbox с visual studio express

PS: или боишься, что понравится, и линуксы снесёшь

fornlr ★★★★★
()
Последнее исправление: fornlr (всего исправлений: 1)
Ответ на: комментарий от zamazan4ik

бред препода из университета

Есть такие люди, у которых их частный случай является неоспоримым доказательством общего поведения.

nezametny
()
Ответ на: комментарий от zamazan4ik

Ну ищи на торентах xdk от первого xbox - там есть chm в котором о некоторых потрохах компилятора рассказывают.

cnupm
()

Не верь им, это морды у них такие...

В msvc - куча подобных отклонений от стандарта, из свежего - недавно на лоре обсуждалась передача по неконстантной ссылке временного обьекта в функцию.

Это вендорлоки от мелкомягких, что бы потом, при портировании прожки на линух и другие нормальные платформы все манагеры кричали громко - фу, эти ваши линух и макоси, на них ниче не конпиляется и всё падает.

Лично я считаю, что это часть политики embrase, extend and extinguish выжеозначенной конторы. Когда они попробовали так (ну пусть не так, а чуть по жёще) сделать с java - заплатили sun 20kk$. Хотя че им эти 20 жалких лямов...

Разработчики на плюсах молча кушают кактус, ну может обсирают msvc в коментах на хабре или тут. Т.к. владельца у языка нет, есть только комитет по стандартизации.

pon4ik ★★★★★
()

В официальной доке, про порядок вычисления аргументов ничего не сказанно, в отличии от темы про rvalue.

pon4ik ★★★★★
()
Ответ на: комментарий от zamazan4ik

Объясняю - я хочу выяснить, правда это или нет. Вдруг это есть в спецификации компила вижлы?

Нет никакой «спецификации». И даже, если бы была...

Сишка и плюсы — весьма специфические языки... В них целочисленные арифеметические операции неассоциативны, и даже (о ужас!) некоммутативны. Т.е. понятно, что во вменяемых архитектурах сложение и умножение коммутативно, но к сишке это не относится.

Операции с плавающей точкой, по определению, неассоциативны и некоммутативны.

Т.е. не нужно злоупотреблять разлапистыми expression'ами. Тем более, в плюсах где перегружается всё (кроме точки, но этот недостаток обещали исправить). Могут быть сюрпризы.

Macil ★★★★★
()

Шах и мат. Даже в спецификации к MSVC, утверждается что однозначно порядок определен только для логических операторов.

А в конкретном примере:

There is no specified order of evaluation among the arguments or the function-call expression.

Пруф здесь:

https://msdn.microsoft.com/ru-ru/library/d45c7a5d(v=vs.100).aspx

P.S. И вообще нечего давить на преподавателя, у всех есть пробелы в знаниях и предрассудки. Вот ты например хочешь тыкать ему на стандарт, вместо того, чтоб раз решить свою и его проблему.

P.P.S. ты ж программист, документацию читать не охота?

anonymous
()
Ответ на: комментарий от zamazan4ik

Источник вопроса - бред препода из университета

Тебе больше заниматься нечем? Охота получить «банан» и укатить в войска?

Запомни, юноша, *никогда* и *никого* никуда не тыкай мордой. Тем более, публично. Это, как минимум, некультурно.

Не стоит ждать заоблачных знаний плюсов от обычного препода в универе. Профессиональные разработчики с приличной зарплатой иногда в продакшен такую херню кидают...

Твоя основная задача не понты кидать, а подготовиться к выходу C++17, который будет актуальным по мере твоего освобождения из мест принудительного получения знаний. Если, конечно, это для тебя важно.

Macil ★★★★★
()
Ответ на: комментарий от anonymous

На него никто и не давил. Но разве это нормально, что тебе говорят, что ты дуралей, и порядок вычисления в выражении строго слева направо? Я считаю, что нет. Тем более, что это и не так.

Теперь по этой доке. Я читал её. Но разве function call expression это выражение, откуда вызывается функция? Вроде как пункт, который Вы указали, относится к тому, что не определен порядок именно между вычислениями аргументов функции и именем функции(то есть он сначала может аргументы посчитать, а потом уже смотреть, что за функция такая их вызывает.мы же указатель на функцию можем вернуть из другой функции, например ). Или я что-то не так понял?

zamazan4ik ★★
() автор топика
Ответ на: комментарий от Macil

В армию я не годен.

А толку мне понты кидать? То есть мне сейчас молча просидеть, а потом на экзамене сказать не то, как правильно, а то, что он хочет услышать? По идее, везде так надо делать. Ладно, чёрт с ним, с преподом. Меня больше намного интересует именно поведение компила

zamazan4ik ★★
() автор топика
Ответ на: комментарий от nezametny

Не, он вроде толковый. Только мне нужны железобетонные пруфы

zamazan4ik ★★
() автор топика
Ответ на: комментарий от anonymous

Left operand of the logical AND operator (&&). The left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated.

А что получается по хорошему так нельзя?

if(!date.isNill() && date.isFirstMonth())

Тоесть возможно будет вычислен второй операнд и я получу краш?

fornlr ★★★★★
()
Последнее исправление: fornlr (всего исправлений: 1)
Ответ на: комментарий от fornlr

Тоесть возможно будет вычислен второй операнд и я получу краш?

Нет. Для && и || порядок вычислений как раз гарантируется.

Если у && слева 0, то нет необходимости вычислять право. Точно также и у || . Eсли слева 1, то нет необходимости вычислять право.

Macil ★★★★★
()
Ответ на: комментарий от fornlr

Нет, даётся гарантия, что сначала вычислится слева, а потом возможно посчитает правое

zamazan4ik ★★
() автор топика
Ответ на: комментарий от zamazan4ik

Да, ты прав, это не то.

Но, я нашел тебе пруф, если тебе хочется увидеть доказательство того что это UB.

В MS тоже не бараны сидят, и компилятор, в целом, умеет вычислять сайд-эффекты, и остается только намекнуть ему что есть путь проще.

случай а) режим отладки: здесь всё просто. Код генерируется как есть, слева направо, в порядке описания. тупо и не интересно. Никакого неожиданного поведения. Никакого реордера нет и быть не может. Не интересно

случай б) релиз с оптимизацией в скорость. Компилятор может понять что желание юзера - не оптимально, и стоит сделать подругому! И тут бац, и вы выясняем что компилятор не ограничен порядком вызова.

пруф:

#include <cstdlib>

int x() {
	printf("x called\n");
	return 0;
}

int y() {
	printf("y called\n");
	exit(-1);
	return 1;
}


int main()
{
	int z = x() + y() + x() + y() + x();;
    return 0;
}

Процедура y() для релиза будет вызвана перед всеми остальными, и пристрелит нафиг программу

Нужно ли это показывать преподу - это вопрос морали. Но это даст ответ на твой вопрос: Нет, MSVC как и остальные, не гарантирует порядок вычисления операндов, если не сказано обратное)

anonymous
()
Ответ на: комментарий от anonymous

Спасибо большое за пример. Насчёт покажу или нет - не знаю. Может просто на кафедру подойду и покажу Ваш пример. Пример интересный.

Всем спасибо за помощь. Надеюсь,что никто такого в коде не встретит в реальных проектах.

zamazan4ik ★★
() автор топика
Ответ на: комментарий от zamazan4ik

а потом на экзамене

А схера ли этому вопросу там возникнуть? Но даже если возникнет, то ты спокойно сошлёшься на языковой стандарт, вы вместе спокойно разберёте соответствующий пункт и тепло и радостно расстанетесь.

Меня больше намного интересует именно поведение компила

Тебе уже несколько раз объясняли, что поведение компилятора в данном случае не определено. Нужно постичь главный дзен сишечки.

Первое. Определено, что поведение не определено, а значит оно не определено, потому что, сука, так определено в стандарте.

Второе. Не определено как должно проявляться неопределённое поведение. Из этого следует, что неопределённое поведение может никак не проявляться.

Macil ★★★★★
()
Ответ на: комментарий от Macil

Нет. Для && и || порядок вычислений как раз гарантируется.

Если у && слева 0, то нет необходимости вычислять право. Точно также и у || . Eсли слева 1, то нет необходимости вычислять право.

Но только если эти операторы не перегружены

Uter
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.