![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
null56 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 2 Всего: 12 |
Собственно вопрос относится скорее к особенностям компиляции... собственно код
Всегда интеросовал этот момент, но всегда старался его избегать Вопрос: всегда ли данный код будет отрабатывать как надо и не вылетит мне с segmentationОМ? То есть всегда ли компилятор отработает условие слева раньше правого или все - таки это зависит от конкретного компилятора? Или стоит всегда использовать верный способ
Надеюсь не сочтете мой вопрос слишком глупым, но мне интересно.... Заранее благодарен за помощь |
||||
|
|||||
GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 15 Всего: 26 |
if (p_my_class && p_my_class->myMethod())
эквивалентно if (p_my_class) { T r=p_my_class->myMethod(); if ® |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 2 Всего: 12 |
GoldFinch, гарантировано на любом компиляторе?
|
|||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
всегда. это т.н. вычисления по ускоренной схеме. Т.е. нет смысла проверять правый операнд, если левый будет равен 0. аналогично для операции || только обратитите внимание, что ускоренный вычисления работают только тогда, когда вы не переопределяете их явно. т.е. если вы в классе напишете operator&&(...) то это значит, что теперь забота о порядке вычислений лежит на вас. |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 2 Всего: 12 |
zim22, ну вопрос в том, чтобы компилятор не проверил правое условие и если оно верное начал проверять левое... потому что после проверки второго вперед первого, вылетит ошибка сегментации....
Вот я и спрашиваю, любой компилятор будет проверять условия слева направо, а не наоборот??? а не то, отработает ли второе, если первое ложно |
|||
|
||||
Fazil6 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
да гарантировано. Из-за этой гарантии нерекомендуется перегружать операторы && и || Добавлено через 4 минуты и 17 секунд операторы && и || гарантируют порядок вычисления операндов стандартом. Это и является залогом того что второй операнд в зависимости от первого может не вычисляться. т.е. второй никогда не будет вычислен перед первым если ты не будешь переопределять эти операторы |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
null56, из умной книжки:
Логические операторы AND и OR всегда обрабатывают свой левый операнд раньше правого. Правый операнд обрабатывается только тогда, когда левый операнд не определил результат однозначно. Такой способ обработки значений называют вычислением по сокращенной схеме (short-circuit evaluation) |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 2 Всего: 12 |
Fazil6, спасибо, теперь понятно... то есть это на уровне стандарта получается...
Спасибо всем.... Добавлено @ 15:29 zim22, спасибо так понятнее Это сообщение отредактировал(а) null56 - 2.4.2009, 15:29 |
|||
|
||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
null56, в арифметических операциях порядок не определён (a + b - неизвестно что сначала будет вычислено a или b), в вызове функции порядок вычисления аргументов (f(a, b, c) - a b или с, или c b или a, и может даже b a c), а логические && || и запятая (которая в роли операции, то есть f(a, (b , c), d) аргументы будут вычислятся в любом порядке, а второй аргумент (b, c) только слева направо)
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
не надо смешивать в одну кучу порядок_выполнения, точки_следования и "сокращенные_вычисления" ![]() |
|||
|
||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
&& , и + - это операции
, - может не быть операцией порядок вычисления в операциях определён чётко, а то, что к ним не относится, может варьироваться
здесь () -> имеют приоритет выше, чем у &&, постфиксные выражения выполняются слева направо поэтому будет -> потом () и вопрос видимо в том, может ли быть компилятор, который среагирует на приоритет значит в стандарте должно быть где-то записано, что выражения с && || всегда выполняются слева направо, независимо от содержимого их операндов Это сообщение отредактировал(а) inside_pointer - 3.4.2009, 02:35 |
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
точнее сказать операторы, а вот результат их применения называется операцией
не до конца понял мысль...
|
||||||
|
|||||||
inside_pointer |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
ну, аргументы в вызове идут через запятую, она не является операцией и её свойства зависят от свойств вызова функции, а когда она в списке объявления типа int i, a, b, c;, то её свойства зависят от свойств объявления, а когда она операция, тогда она работает везде одинаково и однозначно
чтобы это всё срабатывало так, как срабатывает, необходимо, чтобы приоритет операции && был выше, чем приоритет -> и (), иначе должна быть запись о том, почему она, находясь ниже по приоритету, выполняется первее, чем операции находящиеся выше
почему операция -> не выполнится первее && ? |
||||||
|
|||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Вы путаете для чего нужен приоретет операций... Его действие сказывается только на зависимых операциях. почему "не" ? операция -> выполнится вперед операции &&, но до нее дойдет только в случае, если p_my_class "правдив." Это сообщение отредактировал(а) mes - 3.4.2009, 17:53 |
|||
|
||||
Ln78 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 274 Регистрация: 25.11.2006 Репутация: 13 Всего: 15 |
||||
|
||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
почему она будет так выполняться, каким образом она проверит, что первый операнд правдив, по какому правилу ? что значит зависимые операции ? Ln78, он спросил так, как спросил - не разыменуется ли нулевой указатель ![]() |
|||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
по такому правилу: если в результате вычисления выражения мы получим 0 - то FALSE, иначе - TRUE http://forum.vingrad.ru/index.php?showtopi...t&p=1831461 |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
те которые имеют общий операнд. 10-2*3 // - и * зависымые и вначале выполнится умножение потом вычитание10 10-5+2*3 // - и * не зависимы друг от друга и порядок их выполнения не определен.
воэьмем пример : a && ++b; у ++ приоритет больше, но до нее дойдет только если а is true т.е вышеупомянутое выражение разбивается на операции следующим условным образом
inside_pointer, и вдумайтесь так же, что написал Ln78 Это сообщение отредактировал(а) mes - 4.4.2009, 10:26 |
||||
|
|||||
GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 15 Всего: 26 |
||||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
я знаю! я знаю! можно я отвечу! можно!? можно!? ![]() |
|||
|
||||
inside_pointer |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
это 10-5+(2*3), не определён порядок для операции +, то есть может выполниться как и умножение сначала, так и вычитание однако не будет чего-нибудь типа 10-(5+2)*3 или ((10-5)+2)*3, то есть операции по приоритетам выстроены однозначно
почему вот здесь, когда у && низкий приоритет, не может быть такого, что выполнится -> ? zim22, понимаешь у них приоритет разный у -> самый высокий, а у && чуть ли не как у присваивания и тут получается, что у неё приоритет не выше, чем у ->, так как, действительно, метод бы вызывался из 0 или 1, но при этом есть какое-то правило, которое выше приоритета, а формулировки его чо-то не видно, почему оно выше приоритета |
||||
|
|||||
GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 15 Всего: 26 |
||||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
йес! && - это логическая бинарная операция , - это оператор, который используется в случаях, где ряд выражений отделяется запятыми. Выполнены будут все операнды оператора в отличии от &&, где второй операнд будет выполнен, только если первый операнд был true А вообще это две разные операции, которые никак друг с другом не связаны. и они не взаимозаменяемы ![]() Добавлено через 1 минуту и 26 секунд вы не могли бы как-то выделять обращение ко мне. а то я еле нашёл в тексте, что вы и мне отвечали. Это сообщение отредактировал(а) zim22 - 4.4.2009, 13:41 |
|||
|
||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
zim22, GoldFinch спрашивал немножко не об этом.
его интересовало, почему "," не всегда оператор. Потому что иногда она является обычным разделителем, например в списке параметров. ![]() |
||||||
|
|||||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
да там инфа не важная, если пропустишь, ничо не изменится ![]() |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Как раз для + определен. Она выполнится 3й. После - и *. А вот кто из последних двух выполнится первым не определено. А вот в выражении (10-5) && (2*3) порядок определен. Первым выполнится -, потом (если условие верно) выполнится *, и самым последним &&. Как видите приоретет в случае не связанных операций влияния на порядок исполнения не оказывает. Добавлено @ 14:46
правило которое отличает + от && в только что упомянутом примере уже цитировалось в этой теме. Попробуйте найти его сами ![]() Это сообщение отредактировал(а) mes - 4.4.2009, 14:57 |
||||
|
|||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
а, тут типа слева направо происходят все вычисления, то есть разность будет найдена самой первой, так как её приоритет выше &&, сначала не будет проверено что (10-5) истина, сначала выполнится 10-5 а потом этот результат будет проверен, так как встречается следующая операция - && в итоге получаем, что значения в скобках читаются, а потом выполнение выражений внутри начинается слева направо (есть там логические операции или нет) |
|||
|
||||
mes |
|
||||||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
нет, нет и еще раз нет. приоретет нужен всего лишь чтоб разбить на пары:
логично предположить что для оператора && тогда должна получиться аналогичная последовательность действий
однако из за того, что компилятoр должен соблюдать правило сокращенных вычислений, получается так
можно подойти еще с другого конца так например
а теперь попробуйте записать в такой же форме выражение (10-5)&& (2*3) с соблюдением вышеназванного правила ![]() Это сообщение отредактировал(а) mes - 6.4.2009, 02:04 |
||||||||||
|
|||||||||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
Всё, терь кое-что проясняется
![]() |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
![]()
![]() Это сообщение отредактировал(а) mes - 6.4.2009, 03:09 |
||||
|
|||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
а как она проверит first operand ? как она узнает, что first operand - это first operand, она дойдёт до операции && после -, потому что у - приоритет выше, а у -> ещё выше, чем у - получается эта проверка первого операнда выше всех операций, так как не выполняет второй операнд, хотя там содержится операция ->, потому что знает, что это second operand и его выполнять нельзя, пока не пройдёт проверка для first operand |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
проверка и сама операция && не одно и то же, это два разных действия. грубо говоря bool res = a1 && a2, в реальности является :
где __&& "обычный"(без соблюдения правила сокращенногo вычисления) логический оператор АND . |
||||
|
|||||
Fazil6 |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
ты вообще сам читаешь что пишешь? куда оно дойдет? Приоритет операций определяется до того как вычисляются выражения. И во время определения приоритета определяется какое выражение будет операндом какой операции и после этого начинается вычисление операндов
если уж ты хочешь с точки зрения приоритета : a1 && a1->a - тут && самый низкий приоритет, значит его операндами будут выражения a1 и а1->a. И только тут начинается вычисление операндов. Так что до операции && она дойдет намого раньше, чем начнет вычислять операнды. И какой из них правый, а какой левый компилятор всегда знает. При реализации выражений как правило строится дерево. Корень - оператор с наименьшим приоритетом. Левая ветка - выражение левого операнда , правая - правого. Левый и правый в свою очередь такиеже деревья начинающиеся с самой неприоритетной операции и левого и правого выражений операндов этого оператора. Приотритет нужен для построения этого дерева и ничего при этом не вычисляется. А вычисляться начинает тогда, когда уже порядок вычисления выражения четко определен и приоритет операторов дальше уже никак ни на что не влияет. Обходим сначала левую часть дерева - получили первый операнд. Потом обходим правую - второй. Так что никаких противоречий. |
||||
|
|||||
0xDX |
|
|||
Новичок Профиль Группа: Участник Сообщений: 44 Регистрация: 6.2.2009 Репутация: нет Всего: нет |
Вообще то компилятор способен оптимизировать.........
пример
Здесь компилятор способен увидеть что лучше проверить сначало j на ноль(так как проверка на ноль выполняется быстрее, это свойство процессора), а потом думать что делать дальше. Так же в этом примере, не имеет разницу какое условие проверять первым(логического смысла), но здругой староны эту работу должен проделать программист, на уровне привычки........... |
|||
|
||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
ну вот же оно, это правило ![]() как оно следует из стандарта ? тем, что не определено обратное ? |
|||
|
||||
Fazil6 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
о, еще один... нельзя тут оптимизировать. ты читал предыдущие сообщения?
о чем речь вообще? какое правило? Стандарт тут причем? Я привел пример того как в компиляторе может быть реализовано вычисление выражений. Стандарт это не определяет. Можно и подругому - главное чтобы правильно работало. В стандарте написано, что оператор && имеет фиксированный порядок вычисления аргументов отличный от обычных операторов. Как это в компиляторе реализуют никого в стандарте не колышет. Я привел пример как можно это сделать, зачем используется приоритет и как фиксировать порядок вычисления. |
|||
|
||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
То есть, иными словами, в стандарте написано, что правый операнд никогда не вычислится раньше левого, а дальше компиляторы могут писать как хотят и реализовывать вычисления как хотят, главное чтобы это правило работало. Поэтому все предпочитают строить дерево от самой нижней операции, потому что так удобнее делать, а не потому что так в стандарте заложено. |
|||
|
||||
Ln78 |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 274 Регистрация: 25.11.2006 Репутация: 13 Всего: 15 |
inside_pointer, на первой странице приводили цитату из стандарта. Не просто никогда не вычисляется раньше, но и никогда не вычисляется вообще, если первый аргумент false, например, здесь
изменение значения j при отрицательном i никогда не должно проводиться. |
||||
|
|||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Есть две формы записи ариф. выражения. 1. арифметическая a=4+b*6-c; 2. функциональная op-(op+(4,op*(b,6)),c); // где op - operator первая нужна для удобства записи человеком, вторая для трансляции кода компилятором. приорететы нужны, чтоб приводить первую форму записи ко второй и в дальнейшем не используются. как видите аргументы каждой функции видны еще до начала выполнения. для обычных функций и операторов порядок выполнения не определен, а для && требуется, ..(чтоб не повторяться см. выше в цитатах из стандарта) ![]() |
||||
|
|||||
inside_pointer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 344 Регистрация: 9.3.2008 Репутация: 5 Всего: 12 |
я понял, что он по дереву не пойдёт туда, если пройдёт в первое, если там дерево
|
|||
|
||||
uxoos |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 11.8.2009 Репутация: нет Всего: нет |
Ещё вопрос по теме. Исключяются ли из кода пустые или бессмысленные операторы. Просто использую макросы которые оставляют такой мусор в коде.
Например, что из кода исключится, а что останется?
Знаю что некоторые компиляторы оптимизируют код, выявляют всегда верные условия, не используемые переменные и выдают предупреждения. И ещё, как посмотреть код с раскрытыми и заменёнными макросами? |
|||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
ключ /P добавить в настройки проекта (С\С++-Command line-Additional options) |
|||
|
||||
uxoos |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 11.8.2009 Репутация: нет Всего: нет |
Я добавил(Project-Options-C++Linker-Advanced-Additional options-/P), но в Builder 2010 все по обычному. ![]() Это сообщение отредактировал(а) uxoos - 21.10.2009, 20:10 |
|||
|
||||
zim22 |
|
|||
![]() depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 24 Всего: 69 |
![]() они по этому пути выставляются: project properties->c/c++->preprocessor->generate preprocessed file попробуй добавить ключ -P к опциям компилятора. где добавлять - не знаю. |
|||
|
||||
uxoos |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 11.8.2009 Репутация: нет Всего: нет |
Неа. Ладно
![]() ![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |