Доброе время суток! Надеюсь, хоть и сомневаюсь, что тут найдутся знатоки стандарта Си(++). Суть вопроса в следующем. Пусть pointer — указатель, скажем, на char. рассмотрим такую конструкцию:
if (pointer && *pointer)
{
...
}
Т.е. мы проверяем корректность указателя на строку, проверяем не пустая ли она, и потом что-то делаем. По стандарту определены порядок выполнения операция слева направо, а так же приоритет. Данная конструкция скомпилится в нечто подобное:
И так на всех компиляторах и платформах, которые мне встречались. Однако, прописано ли явно в стандарте, что второй аргумент && не должен вычисляться? Т.е. если попытка чтения по указателю таки будет выполнена, а потом выполнится &&, это будет противоречить стандартам?
Приведу еще аналогичный случай.
int a = 10;
int b = 20;
int c = 0 ? ++a : ++b;
После выполнения виденными мной компиляторами a == 10, b == 21, c == 21. Однако обязан ли компилятор не выполнять выражение ++a ? Т.е. если результат a == 11, b == 21, c == 21, это правильно с точки зрения стандарта языка?
Здравствуйте, lis_asm, Вы писали:
_>Т.е. если попытка чтения по указателю таки будет выполнена, а потом выполнится &&, это будет противоречить стандартам?
вы уже ответили на этот вопрос выше: слева — направо.
во втором случае так же, выражение ++a вычисляться не будет.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, lis_asm, Вы писали:
_>Доброе время суток! Надеюсь, хоть и сомневаюсь, что тут найдутся знатоки стандарта Си(++).
Странный посыл. Это — один из сильнейших форумов по С++ на русском языке, знатоки стандарта здесь безусловно найдутся.
_>И так на всех компиляторах и платформах, которые мне встречались. Однако, прописано ли явно в стандарте, что второй аргумент && не должен вычисляться? Т.е. если попытка чтения по указателю таки будет выполнена, а потом выполнится &&, это будет противоречить стандартам?
Прописано. [expr.log.and], 7.6.14 в текущем драфте:
[quote]
Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
[/quote]
_>Приведу еще аналогичный случай.
_>int a = 10; _>int b = 20; _>int c = 0 ? ++a : ++b;
_>Однако обязан ли компилятор не выполнять выражение ++a ?
Да, обязан. В данном случае работает другой пункт стандарта, [expr.cond], 7.6.16
[quote]
It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated.
[/quote]
Здравствуйте, lis_asm, Вы писали:
_>И так на всех компиляторах и платформах, которые мне встречались. Однако, прописано ли явно в стандарте, что второй аргумент && не должен вычисляться? Т.е. если попытка чтения по указателю таки будет выполнена, а потом выполнится &&, это будет противоречить стандартам?
В случае Си, да, операнды логических операций выполняются слева на права.
В случае C++ все несколько сложнее. Встроенные логические операции выполняются, как в Си, а вот перегруженные — как компилятору приспичит.
Pzz>В случае C++ все несколько сложнее. Встроенные логические операции выполняются, как в Си, а вот перегруженные — как компилятору приспичит.
При перегрузке &&, ||, по-моему, только отменяется short circuit evaluation, когда значение выражения становится известным при вычислении первого аргумента и второй не вычисляется. Потому что после перегрузки это становится уже не логическое выражение, а какое автор захотел, в результате всегда считаются оба выражения. Однако, ассоциативность слева направо остается.
V>Прописано. [expr.log.and], 7.6.14 в текущем драфте:
V>[quote] V>Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false. V>[/quote]
V>Да, обязан. В данном случае работает другой пункт стандарта, [expr.cond], 7.6.16
V>[quote] V>It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated. V>[/quote]
Спасибо! Собственно это и интересовало. Только в случае интерпретатора это существенно все усложняет, к сожалению..
Здравствуйте, Masterspline, Вы писали:
M>При перегрузке &&, ||, по-моему, только отменяется short circuit evaluation, когда значение выражения становится известным при вычислении первого аргумента и второй не вычисляется. Потому что после перегрузки это становится уже не логическое выражение, а какое автор захотел, в результате всегда считаются оба выражения. Однако, ассоциативность слева направо остается.
Я не про ассоциативность, а про порядок вычислений.
С оператором "запятая", кстати, та же самая история.
V>Прописано. [expr.log.and], 7.6.14 в текущем драфте:
V>[quote] V>Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false. V>[/quote]
С && все понятно, но с &... Например, так:
int a = 10;
int b = false & a++;
Ну или
int a = 10;
int b = 0 & a++;
На VS2012, VS2017 инкремент таки происходит... Выходит, или компилятор неправильно работает, или на этот счет разные стандарты..
Здравствуйте, lis_asm, Вы писали:
V>>Прописано. [expr.log.and], 7.6.14 в текущем драфте:
V>>[quote] V>>Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false. V>>[/quote]
_>С && все понятно, но с &... Например, так: _> int a = 10; _> int b = false & a++; _>Ну или _> int a = 10; _> int b = 0 & a++; _>На VS2012, VS2017 инкремент таки происходит... Выходит, или компилятор неправильно работает, или на этот счет разные стандарты..
Здравствуйте, lis_asm, Вы писали:
_>Доброе время суток! Надеюсь, хоть и сомневаюсь, что тут найдутся знатоки стандарта Си(++).
Да воздастся каждому по желаниям его.
_> Суть вопроса в следующем. Пусть pointer — указатель, скажем, на char. рассмотрим такую конструкцию: _>if (pointer && *pointer)
Стандарт гарантирует, что если оператор && не перегружен, то второй оператор не выполнится при (bool)pointer == false
на самом деле здесь семь операций:
1) cast к (bool) переменной pointer'а
2) сравнение (bool)pointer с true
3) ЕСЛИ pointer не нуль, И operator&& НЕ перегружен, ТОГДА (выполнить следующие 4 пункта)
4) разыменовать указатель
5) привести *pointer к bool
6) сравнить (bool)*pointer с true
7) выполнить && (будет выкинуто компилятором, если operator&& не перегружен)