Я попытался найти ответ в Интернете, но не нашел его.
Сегодня я увидел эти строки кода:
int main(){
int n = 7;
while(n /= 10);
}
В этом нет особого смысла, но вопрос был только в том, будет ли он компилироваться? На что я ответил отрицательно, но ошибся.
У меня вопрос, а почему? Почему
n /= 10
вести себя как bool (или int) здесь?
Оператор / = правильный и эквивалентен: (n = n / 10) Так же, как оператор + =, который эквивалентен: (n = n / 10)
В будущем вы будете в ужасе от того, сколько компилируется, когда вы этого не хотите.
Присвоение (включая составное присваивание, такое как /=
) - это выражение, которое дает значение, которое было присвоено 1.
Итак, вы можете сделать что-то вроде: x = y = z = 0;
, который присваивает 0 z
, берет результат этого (также 0) и присваивает его y
, а результат этого (по-прежнему 0) присваивает x
.
Оттуда он использует неявное преобразование из int
в bool
, при котором 0
преобразуется в false
, а любое ненулевое значение преобразуется в true
.
1. Note: that's what happens for built-in types. By convention, when/if you overload operator=
for a class, you have it return *this;
, so it works the same way, as a user would/will expect--but that part's not mandatory--you can overload your operator=
to return a different value or an entirely different type--but this is almost always a bad idea and should usually be avoided.
C++ преобразует n / = 10 в bool. Целые числа = 0, преобразованные в логическое значение, оцениваются как ложные. Целые числа! = 0, преобразованные в логическое значение, оцениваются как истина.
Это пока будет оцениваться как while(false)
.
Нет, он не будет работать вечно, потому что n
будет изменять каждую итерацию цикла.
Целые числа! = 0 ложны.
@stark: Нет, целые числа == 0 - ложь, целые числа! = 0 - истинные.
на самом деле он не будет запускаться ни разу
Editet, целые числа! = 0 истинны.
Итак ... почему он не запускается?
@JacoAlberts 7/10 - 0, т.е. ложь.
@JacoAlberts Оператор /=
"Итак ... почему он не запускается?" для встроенных типов возвращает присвоенное значение. Поскольку n
- это 7
перед первой итерацией, n /= 10
вернет 0
, который будет рассматриваться как false
, и, следовательно, ни одна итерация тела цикла не будет оцениваться.
Он действительно работает, но не вечно. n - это int, 7/10 = 0,7, преобразовать в int = 0, результат будет ложным. Так запускается один раз. В этом примере нет тела цикла для выполнения. Бит Я согласен, если бы было тело цикла, оно бы не выполнялось. Сразу говорю, программа запускается.
Обновлен исходный ответ
@JacoAlberts "Бит Я согласен, если бы было тело цикла, оно бы не выполнялось." Есть тело цикла. Он состоит из одного пустого оператора.
Вот что у вас есть для цикла while:
while ( expression );
Если экспрессия - true
или non 0
, цикл будет продолжен; в противном случае, если он оценивается как false
или 0
, он будет завершен. Итак, оглядываясь на свой оригинал:
int n = 7;
while ( n /= 10 );
Тогда это становится:
while ( n = 7 / 10 );
Здесь полное выражение - n = 7 / 10
; Это должно привести к 0
из-за усечения целочисленной арифметики. Значение неявного преобразования из int
в bool
становится false
. В результате получился 0
.
Здесь ничего не мешает компиляции. Поскольку это ничем не отличается от наличия:
while ( false );
Однако с присваиванием и арифметическими операциями; это может быть не всегда так, но в вашем случае это так. Рассмотрим следующий пример: он все равно будет компилироваться, но цикл не завершится:
int n = 5;
while( n + n );
Тогда это станет:
while( 5 + 5 );
...
while( 10 );
...
while( true );
Что по-прежнему будет компилироваться, но цикл будет продолжаться бесконечно.
Разве n = 7/10
не будет 0, поскольку значения целые? В остальном ответ довольно ясен.
@auouo 7/10 зависит от компилятора и того, как он выполняет целочисленную арифметику. Если он усекает его, то да, это будут 0
и false
, но если нет и увидит, что это не значение 0
, он будет рассматривать его как true
. Однако я думаю, что вы правы, говоря, что это 0
.
@auouo Я отредактировал свой ответ, чтобы отразить это, поскольку я забыл об усечении ....
+=
и -=
работают так же, как *=
и /=
.
На самом деле есть еще &=
и |=
.
Все они оценивают новое значение, которое было присвоено.
И, как вы знаете, вам не нужно помещать логическое значение в условие while
/ for
/ if
; вам нужно только поместить туда что-то, что может быть преобразованный для логического значения.
Например, if (42)
, или for (char* ptr = begin; ptr; ++ptr)
, или while (n /= 10)
.
Любое ненулевое значение рассматривается как
true
в C++.