сэр, пожалуйста, скажите мне, почему следующее условие в 'C' является false
?Использование условия
main()
{
int i=1;
if(i<=i++)
printf("false");
else
printf("true");
}
сэр, пожалуйста, скажите мне, почему следующее условие в 'C' является false
?Использование условия
main()
{
int i=1;
if(i<=i++)
printf("false");
else
printf("true");
}
Это не ложь, вы просто печатаете false
, когда это правда.
Это также неопределенный, не так ли? –
Все еще указывает на ошибку, –
@Paulpro: Неопределенное поведение. Доступ и отдельная модификация объекта без промежуточной точки последовательности имеет неопределенное поведение, за C 2011 (N1570) 6.5 2. –
Чтобы понять, что ваш код делает, я собираюсь переписать, только будет очень четко:
main()
{
int i=1;
if(i<=i) {
i++;
printf("false");
} else {
i++:
printf("true");
}
}
i++
означает приращение I после сравнения. В обеих ветвях if if увеличивается, поэтому он эквивалентен.
Этот код предназначен для объяснения, а не быть примером хорошего кодирования. Тот, кто проголосовал за мой ответ, не понимает, что я пытаюсь сделать onstrate. – JackCColeman
Я проигнорирован, потому что вы не можете гарантировать, что выбранный вами заказ (левая сторона '<=' оценивается перед правой стороной '<=') будет упорядочением, используемым компилятором. –
В 'i <= i ++', стандарт C позволяет реализации увеличивать 'i' до или после принятия значения' i' для левой стороны '<='.Кроме того, это означает, что 'i' может быть модифицировано и отдельно использоваться без промежуточной точки последовательности, которая имеет неопределенное поведение. –
Оператор сравнения <=
не определяет, какая сторона будет оцениваться во-первых, i
или i++
, и нет никакого смысла последовательности в конце левого операнда на функцию сравнения (см http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Sequence-Points).
Если левая сторона вычисляется первым, вы получите:
if (1 <= 1)
Если правая часть оценивается первым, вы получите:
if (2 <= 1)
Это выдвигает на первый план проблему, но это еще хуже.
Вы написали код с неопределенным поведением, что означает точно, что «неопределено». Компилятор может сделать anything в этом случае и по-прежнему соответствовать стандарту.
Например, эти компиляторы (с -O3
) следуют еще ветвь:
Хотя эти компиляторы (с -O3
) следуют true
ветви:
g++-4.7 (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
И другие компиляторы могли сделать что-то совершенно другое.
Даже если он работает, но его трудно понять. Некоторый человек через несколько лет (даже, может быть, сам) должен выяснить, что именно делает линия кода. В этом много проблем. Почему люди не могут легко читать и понимать? Безопасность работы - единственное объяснение того, что я не писал легко читаемый код. Я чувствую себя –
@ Санчо, он может быть неопределенным (я не согласен или не согласен на этот вопрос), но это может быть разумным. Почему человек, который написал компилятор, был бы необоснованным, сверхъестественным или иным образом противным? – JackCColeman
@JackCColeman Вы не согласны с тем, что это неопределенное поведение? Да, полученное поведение * может быть разумным, но это не гарантировано. –
Это комбинация unspecified behavior и простая и простая undefined behavior. Таким образом, вы не можете предсказать результат этого кода, и на результаты нельзя положиться.Это не определено, потому что в этой строке:
if(i<=i++)
мы не знаем, будет ли оцениваться сначала i
или i++
. пункт draft C99 standard раздел 6.5
говорит:
группирования операторов и операндов обозначается syntax.74) За исключением случаев, указанных ниже (для вызова функции(), & &, ||,? :, и операторы запятой), порядок оценки подвыражений и порядок, в котором происходят побочные эффекты, не определены.
Вышеуказанная линия также является неопределенным поведением, потому что между sequence points мы только разрешено модифицировать переменные один раз, и если мы изменим его, мы только разрешено читать предыдущее значение, чтобы определить новое значение для установки. В этом случае мы считываем значение, чтобы определить как i
, так и i++
. Из проекта стандарта раздел пункт 6.5
:
Между предыдущей и следующей точкой последовательности объект должен быть его сохраненное значение изменено в самый раз по оценке выражения. Кроме того, предыдущее значение должно быть считано только для определения значения, которое необходимо сохранить.
Это домашнее задание? – MAK
Пожалуйста, не пишите код типа 'if (i <= i ++)'. Отделите две операции на две отдельные строки. Сделайте вашу жизнь проще в долгосрочной перспективе. –
Как @Sancho пишет в своем ответе, это неопределенное поведение. Особое место в программистом ад для людей, которые думают, что все в порядке, пожалуйста, не пишите такой код. :-) – asveikau