2017-01-13 2 views
0

Я не могу понять, как это выражение будет оцениваться в C? Я немного смущен оценкой выражения внутри printf? Если выражение внутри printf оценивается справа налево, тогда оценка выражения должна была прекратиться после встречи (c> 10), но напечатала '1' на экране вывода?Как это выражение будет оцениваться в C?

Это не точный синтаксис C, а вопрос, который мне задали.

integer a = 50, b = 25, c = 0; 
printf(a > 45 || b > 50 && c > 10); 
+1

'a> 45 || b> 50 && c> 10' будет группироваться как '(a> 45) || (b> 50 && c> 10). Порядок оценки подвыражений будет идти слева направо. – haccks

+0

Кроме того, проверьте: http://en.cppreference.com/w/c/language/operator_precedence –

+0

Пожалуйста, не пишите такой код, вы получите пару дополнительных круглых скобок; –

ответ

1

Это было бы неопределенное поведение. Первый аргумент printf должен быть строкой формата. Скорее всего, он потерпит крах. Что экономит вас, так это то, что «integer» не является типом, поэтому он не собирается компилироваться.

+2

Это, наверное, я, кто несет ответственность. Я фиксировал форматирование, которое делает это похожим на точный код, но OP уже упоминался. Это не точный синтаксис C_, поэтому я думаю, что OP это знает. –

2

Это выражение

a > 45 || b > 50 && c > 10 

эквивалентно выражению

(a > 45) || (b > 50 && c > 10) 

Таким образом, если эта Подвыражение (a > 45) оценивается как истина, то второй Подвыражение не будет оценивать и результат равен 1 (типа Int) ,

В противном случае это выражение к югу

(b > 50 && c > 10) 

эквивалентно

(b > 50) && (c > 10) 

, если (b > 50) принимает значение ложь, то в целом результат является ложным (0 в C), а второй Подвыражение не будет оценивать. В противном случае результатом будет значение подвыражение c > 10. Если c > 10 то результатом является объектом типа Int со значением 1 или если не (c > 10) то значение результата 0.

Если переменные имеют значения, как это показано в вашем вопросе

int a = 50, b = 25, c = 0; 

то первое подвыражение

a > 45 

оценивает true, и результат 1 типа int. Второе подвыражение

b > 50 && c > 10 

даже не оценит.

Рассмотрим следующий пример показательной программы

#include <stdio.h> 

int f(int x) 
{ 
    printf("f is called for %d\n", x); 
    return x; 
} 

int main(void) 
{ 
    int a = 50, b = 25, c = 0; 

    f(f(a) > 45 || f(b) > 50 && f(c) > 10); 

    return 0; 
} 

Его выход

f is called for 50 
f is called for 1 

Как вы можете видеть, что это было достаточно, чтобы вычислить выражение f(a) > 45, чтобы получить результат, равный 1.

+0

Ты потрясающий. Эта концепция не может быть объяснена более четко, чем это. Спасибо, что ответили на мой вопрос. –

+0

@ KartikChauhan Нет вообще. Добро пожаловать.:) –

0

контекст, в котором это выражение появляется влияет ли вычисляется его, но не как.Порядок, в котором оцениваются подвыражения большего выражения, контролируется operator precedence and associativity.

Среди операторов в вашем выражении > имеет наибольшее преимущество, затем &&, затем ||. Все ассоциируются слева направо. Таким образом, ваше выражение вычисляется точно так же, как если бы она была написана так:

(a > 45) || ((b > 50) && (c > 10)) 

Кроме того, && и || операторы выполняют оценку короткого замыкания. Кажется, это путаница для вас. Оценка короткого замыкания означает, что если результат операции && или || определяется значением левого операнда, то правый операнд этой операции не оценивается. Это не влияет на то, выполняются ли операции другие, за исключением того, что результат операции с коротким замыканием используется в качестве операнда.

В этом случае, однако, поскольку || ассоциируется слева направо, сначала оценивается a > 45, производя 1 (true). Поскольку это определяет результат операции ||, его правый операнд не оценивается. Относительный приоритет оператора приводит к тому, что правый операнд является остатком общего выражения, как показано выше, поэтому ни один из них не будет оценен. Даже если это были оценены, результат общего выражения будет по-прежнему 1, так как левый операнд оценивается в 1 независимо от правого подвыражения. Вот почему правую часть || не нужно оценивать.

1

Как операторы , так и && вынуждают левую-правую оценку. Левый операнд будет полностью оценен (и все побочные эффекты) до того, как будет оценен правый операнд.

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

Для

a || b 

, если a верно, то все выражение верно независимо от значения b, поэтому b не вычисляется.

Аналогично, для

a && b 

если a ложна, то все выражение является ложным, независимо от значения b, поэтому b не вычисляется.

&& имеет более высокий приоритет, чем ||, так что

a || b && c 

будет разобрано как

a || (b && c) 

и

a && b || c 

будет разобрано как

(a && b) || c 

Итак ...

a > 45 || b > 50 && c > 10 

обрабатывается как

a > 45 || (b > 50 && c > 10) 

С a == 50, a > 45 верно. Поскольку a > 45 - левый операнд оператора ||, все выражение истинно независимо от правого операнда, поэтому b > 50 && c > 10 не оценивается вообще.

Результат выражения равен 1 (true).

К сожалению, printf ожидает, что его первый аргумент указывает на строку символов (строка формата), а 1, скорее всего, не является допустимым адресом на вашей платформе, поэтому результат этого кода, скорее всего, будет segfault. Легкое исправить было бы написать

printf("%d\n", a > 45 || b > 50 && c > 10); 
Смежные вопросы