2013-08-30 2 views
-1

сэр, пожалуйста, скажите мне, почему следующее условие в 'C' является false?Использование условия

main() 
{ 
    int i=1; 
    if(i<=i++) 
     printf("false"); 
    else 
     printf("true"); 
} 
+0

Это домашнее задание? – MAK

+3

Пожалуйста, не пишите код типа 'if (i <= i ++)'. Отделите две операции на две отдельные строки. Сделайте вашу жизнь проще в долгосрочной перспективе. –

+2

Как @Sancho пишет в своем ответе, это неопределенное поведение. Особое место в программистом ад для людей, которые думают, что все в порядке, пожалуйста, не пишите такой код. :-) – asveikau

ответ

12

Это не ложь, вы просто печатаете false, когда это правда.

+4

Это также неопределенный, не так ли? –

+0

Все еще указывает на ошибку, –

+7

@Paulpro: Неопределенное поведение. Доступ и отдельная модификация объекта без промежуточной точки последовательности имеет неопределенное поведение, за C 2011 (N1570) 6.5 2. –

-3

Чтобы понять, что ваш код делает, я собираюсь переписать, только будет очень четко:

main() 
{ 
    int i=1; 
    if(i<=i) { 
     i++; 
     printf("false"); 
    } else { 
     i++: 
     printf("true"); 
    } 
} 

i++ означает приращение I после сравнения. В обеих ветвях if if увеличивается, поэтому он эквивалентен.

+0

Этот код предназначен для объяснения, а не быть примером хорошего кодирования. Тот, кто проголосовал за мой ответ, не понимает, что я пытаюсь сделать onstrate. – JackCColeman

+6

Я проигнорирован, потому что вы не можете гарантировать, что выбранный вами заказ (левая сторона '<=' оценивается перед правой стороной '<=') будет упорядочением, используемым компилятором. –

+7

В 'i <= i ++', стандарт C позволяет реализации увеличивать 'i' до или после принятия значения' i' для левой стороны '<='.Кроме того, это означает, что 'i' может быть модифицировано и отдельно использоваться без промежуточной точки последовательности, которая имеет неопределенное поведение. –

2

Оператор сравнения <= не определяет, какая сторона будет оцениваться во-первых, 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 ветви:

И другие компиляторы могли сделать что-то совершенно другое.

+0

Даже если он работает, но его трудно понять. Некоторый человек через несколько лет (даже, может быть, сам) должен выяснить, что именно делает линия кода. В этом много проблем. Почему люди не могут легко читать и понимать? Безопасность работы - единственное объяснение того, что я не писал легко читаемый код. Я чувствую себя –

+0

@ Санчо, он может быть неопределенным (я не согласен или не согласен на этот вопрос), но это может быть разумным. Почему человек, который написал компилятор, был бы необоснованным, сверхъестественным или иным образом противным? – JackCColeman

+0

@JackCColeman Вы не согласны с тем, что это неопределенное поведение? Да, полученное поведение * может быть разумным, но это не гарантировано. –

1

Это комбинация unspecified behavior и простая и простая undefined behavior. Таким образом, вы не можете предсказать результат этого кода, и на результаты нельзя положиться.Это не определено, потому что в этой строке:

if(i<=i++) 

мы не знаем, будет ли оцениваться сначала i или i++. пункт draft C99 standard раздел 6.5 говорит:

группирования операторов и операндов обозначается syntax.74) За исключением случаев, указанных ниже (для вызова функции(), & &, ||,? :, и операторы запятой), порядок оценки подвыражений и порядок, в котором происходят побочные эффекты, не определены.

Вышеуказанная линия также является неопределенным поведением, потому что между sequence points мы только разрешено модифицировать переменные один раз, и если мы изменим его, мы только разрешено читать предыдущее значение, чтобы определить новое значение для установки. В этом случае мы считываем значение, чтобы определить как i, так и i++. Из проекта стандарта раздел пункт 6.5 :

Между предыдущей и следующей точкой последовательности объект должен быть его сохраненное значение изменено в самый раз по оценке выражения. Кроме того, предыдущее значение должно быть считано только для определения значения, которое необходимо сохранить.

Смежные вопросы