Много раз я вижу (и иногда пишу) код, похожий на этот пример:
int a=0, b=2; if( a && (b=func())!=0 ) { //...
Вопрос в том, подтверждает ли стандарт эти утверждения?
b
не будет касаться (и останется значением 2
) func()
не будет вызвана И наоборот, если мы напишем if( func()!=0 && a )
– будет вызвана стандартная гарантия func()
?
Меня интересует конкретный стандартный параграф, определяющий это, является законным.
UPD: моя опечатка, измененная от int a=1
до int a=0
Точный вопрос;
Вопрос в том, гарантирует ли стандарт эти утверждения?
К обновленному вопросу; при a=0
. Если a==0
, то да, оценка короткого замыкания будет вызвана, а func()
не будет вызвана; второй операнд не будет оцениваться.
Если a=1
(как было первоначально), наоборот; func()
будет вызываться – a
равно 1
таким образом, «true», в результате вычисляется второй операнд (это логический И), b
будет изменяться. Если бы оператор был ||
(логическое ИЛИ), то оценка короткого замыкания будет вызвана, а func()
не будет вызвана.
И наоборот, если мы напишем
if( func()!=0 && a )
– будет ли вызвана стандартная гарантияfunc()
?
Да, первый операнд всегда оценивается.
Да, оценка короткого замыкания гарантирована для C ++;
§5.14 Логический оператор И
1 Операторы
&&
группируются слева направо. Операнды конвертируются в контекст в bool (раздел 4). Результат верен, если оба операнда верны и false в противном случае. В отличие от&
,&&
гарантирует оценку слева направо: второй операнд не оценивается, если первый операнд является ложным.2 Результатом является bool. Если второе выражение оценивается, каждое вычисление значения и побочный эффект, связанные с первым выражением, секвенируются перед вычислением каждого значения и побочным эффектом, связанным со вторым выражением.
§5.15 Логический оператор ИЛИ
1
||
группы операторов слева направо. Операнды конвертируются в контекст в bool (раздел 4). Он возвращает true, если любой из его операндов истинен, а false – в противном случае. В отличие от|
,||
гарантирует оценку слева направо; кроме того, второй операнд не оценивается, если первый операнд оценивается как истинный.2 Результатом является bool. Если второе выражение оценивается, каждое вычисление значения и побочный эффект, связанные с первым выражением, секвенируются перед вычислением каждого значения и побочным эффектом, связанным со вторым выражением.
Соответствующие кавычки для C:
§6.5.13 Логический оператор И
4 В отличие от побитового двоичного оператора, оператор
&&
гарантирует оценку слева направо; если второй операнд оценивается, то существует точка последовательности между оценками первого и второго операндов. Если первый операнд сравнивается с 0, второй операнд не оценивается.
§6.5.14 Логический оператор ИЛИ
4 В отличие от побитового
|
оператора,||
оператор гарантирует оценку слева направо; если второй операнд оценивается, то существует точка последовательности между оценками первого и второго операндов. Если первый операнд сравнивается не равным 0, второй операнд не оценивается.
Из стандарта C-90.
6.5.13 Логический оператор И
….
4 В отличие от побитового двоичного оператора, оператор && гарантирует оценку слева направо; после оценки первого операнда есть точка последовательности. Если первый операнд сравнивается с 0, второй операнд не оценивается.
Аналогично для логического оператора OR.
Оператор &&
требует, чтобы оба операнда были истинными. Если первый операнд оценивает значение false, то второй операнд не будет оцениваться. Но поскольку a
равно 1, оно считается истинным, а второе выражение (операнд) оценивается. Таким образом, func()
вызывается и ее результат присваивается b
а затем b
проверяется на ненулевое значение.
Стандарт гарантирует, что операторы в последовательности &&
оцениваются слева направо и что, как только один из них оценит значение false, те, которые справа от него, не будут оценены.
Вопрос в том, гарантирует ли стандарт эти утверждения?
b не будет касаться (и останется значением 2)
Функция func () не будет вызвана
Нет, на самом деле оба они ошибаются в этом случае. Потому что это оператор &&
поэтому в этом конкретном случае не может быть применена логика ярлыков.
Если вы измените его на ||
то ваши утверждения верны – только тогда оценка первого операнда ( a = 1
в этом случае) будет достаточной, а остальная часть будет проигнорирована.
Когда вопрос изменился на a = 0
тогда да, оба утверждения правильны и гарантированы.