Вопрос:

Ошибка с потоковыми и условными операторами

c++

43 просмотра

2 ответа

486 Репутация автора

Недавно я столкнулся с ошибкой в ​​моем коде, которая, я думаю, может быть распространенной ошибкой. Я обобщил ошибку, и я хотел бы понять, почему это не генерирует предупреждение или ошибку компилятора. Заранее спасибо.

Ошибка заключается в следующем использовании условного оператора и оператора потоковой передачи для cout:

int i=0;
int array[] = {1};
std::cout << false ? array[i++] : 2;
std::cout << std::endl << "i = " << i << std::endl;

// output:
// 0
// i = 1

Я предполагаю, что первое напечатанное число 0является числовым представлением false. Я не уверен, как компилятор интерпретирует остальное. array[i++]Становится оценено , так как iбыл увеличен. Это должен быть допустимый синтаксис, но интерпретация вообще не ожидается. Либо это?


Для тех, кто допустил ту же ошибку, но не знает исправления, исправленный код имеет круглые скобки вокруг условного оператора:

int i=0;
int array[] = {1};
std::cout << (false ? array[i++] : 2);
std::cout << std::endl << "i = " << i << std::endl;

// output:
// 2
// i = 0

Кроме того, вызов оператора потоковой передачи после условной операции вызвал бы ошибку компилятора:

int i=0;
int array[] = {1};
std::cout << false ? array[i++] : 2 << std::endl;
std::cout << std::endl << "i = " << i << std::endl;

// fails to compile
// error: invalid operands of types 'int' and '<unresolved overloaded function type>' to binary 'operator<<'
Автор: flu Источник Размещён: 17.10.2018 10:14

Ответы (2)


1 плюс

1 Репутация автора

int i = 0;
std::cout << false ? array[i++] : 2;

Результат std::cout.operator<<(bool)преобразования в логическое значение, trueесли std::coutошибка отсутствует, сбой ... состояние. i++оценивается, и весь оператор дает array[0].

Автор: Swordfish Размещён: 17.10.2018 10:21

2 плюса

103026 Репутация автора

Решение

Я предполагаю, что первое число, напечатанное 0, является числовым представлением false.

Правильный.

Я не уверен, как компилятор интерпретирует остальное.

? :является троичным условным оператором. Первое подвыражение ( std::cout << false) оценивается как логическое значение, и если оно истинно, вычисляется среднее подвыражение ( array[i++]), в противном случае оценивается последнее подвыражение ( 2).

std::coutимеет тип std::ostream. Оператор вставки потока возвращает сам поток. В потоке есть оператор преобразования в логическое значение (начиная с C ++ 11; ранее оператор преобразования представлял собой указатель void, который в этом случае ведет себя так же). Поведение оператора преобразования:

Возвращает true, если поток не содержит ошибок и готов к операциям ввода-вывода.

Поскольку в выходном потоке не было ошибок, преобразование возвращает значение true, и поэтому array[i++]вычисляется среднее подвыражение ( ).

Я хотел бы понять, почему это не генерирует предупреждение или ошибку компилятора.

Потому что нет ошибки и (возможно) нечего предупреждать. Возможно, вы намеревались написать что-то еще, но то, что вы написали, является действительной программой, и компилятор не может прочитать ваши мысли, чтобы выяснить, что это не то, что вы намеревались.

Обратите внимание, что если вы удалили какие-либо побочные эффекты из троичных результатов:, std::cout << false ? array[i] : 2;тогда компилятор, скорее всего, предупредит вас, потому что выражение верхнего уровня теперь не имеет побочных эффектов.

PS Clang предупреждает о вашей программе, если вы включили предупреждения:

main.cpp:7:20: warning: operator '?:' has lower precedence than '<<'; '<<' will be evaluated first [-Wparentheses]
std::cout << false ? array[i++] : 2;
~~~~~~~~~~~~~~~~~~ ^
main.cpp:7:20: note: place parentheses around the '<<' expression to silence this warning
std::cout << false ? array[i++] : 2;
                   ^
main.cpp:7:20: note: place parentheses around the '?:' expression to evaluate it first
std::cout << false ? array[i++] : 2;
Автор: eerorika Размещён: 17.10.2018 11:10
Вопросы из категории :
32x32