Условное выражение в тернарном операторе в C

Код

#include <stdio.h>

int main() {
  int i;
  for (i=1; i<=10; i++) {
        (i % 2) ? printf("%d is odd\n", i) : printf("%d is even\n", i);
  }
}

Результат

1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even

Почему в приведенной выше программе C она по-прежнему работает нормально, хотя условное выражение указывает только i%2, а не i%2!=0?


person Akhmad Zaki    schedule 06.12.2019    source источник
comment
i%2 — это выражение скалярного значения. это неявно важно для истинного (ненулевого) или ложного (ноль) в контексте выражения, подобном вашему.   -  person WhozCraig    schedule 06.12.2019
comment
printf ("%d is %s\n", i, i % 2 ? "odd" : "even") тоже работает :)   -  person David C. Rankin    schedule 06.12.2019
comment
Или static const char *msg[] = {"even","odd"}; и в своем цикле вы делаете что-то вроде printf("%d is %s\n", i, msg[i%2]); , но теперь мы уходим от устава вашего вопроса.   -  person WhozCraig    schedule 06.12.2019


Ответы (2)


В C целые числа могут использоваться в логическом контексте, и ноль представляет ложь, а ненулевое значение — истину.

Вот почему ваш код работает. Выражение num % 2 будет равно 0 (единственное ложное значение) для четного числа и 1 (одно из многих возможных истинных значений) для нечетного числа.

Все следующие выражения будут работать для обнаружения нечетного числа:

num % 2
(num % 2) != 0
((num % 2) != 0) != 0
... and so on, ad untilyougetboredum (like 'ad infinitum' but with limits).

Сказав это, я действительно не считаю хорошей идеей делать это таким образом, код должен выражать намерение в максимально возможной степени, и намерение здесь должно состоять в том, чтобы выбрать путь выполнения на основе сравнения. Это означает, что если вы ищете нечетное число, вы должны использовать что-то вроде (num % 2) == 1.

Вам также не нужен отдельный вызов printf в каждом из этих путей кода:

printf("%d is %s\n", num, ((num % 2) == 1) ? "odd" : "even");

Вы заметите, что я также использовал num вместо i. Это просто мой стиль, связанный с вышеупомянутым намерением. Если переменная используется только как индекс, я с удовольствием использую переменные типа i(a), но во-вторых, она получает семантическое свойство (например, число проверяется на странность), Я склонен использовать более описательные имена.

У меня нет проблем с людьми, использующими простые имена переменных, я просто предпочитаю более описательные имена в своем собственном коде.


(a) На самом деле, я бы, наверное, использовал idx в этом случае, но это слишком CDO(b), даже для меня :-)


(b) ОКР, но в правильном порядке :-)

person paxdiablo    schedule 06.12.2019

C не имеет специального типа boolean. Он использует значение int как логическое. То есть 0 считается false, а любое ненулевое значение рассматривается как true. Попробуйте распечатать некоторые условия

printf("%d",5==5);
printf("%d",1>3);

Это выведет 1 и 0.

C всегда использует 1 для обозначения true. Но любое другое ненулевое значение также будет работать при использовании в условиях.

if(6+1)
    printf("TRUE");

Напечатает ИСТИНА.

Это также причина, по которой мы можем использовать эту форму цикла while:

int i= 10;
while(i--){
    printf("%d",i);
}

Напечатает 9876543210. Обратите внимание, что он останавливается, когда i становится равным 0, то есть false.

Теперь вернемся к вопросу, i%2 всегда приводит либо к 0, либо к 1. В случае 1 (истина) выполняется первый оператор, а в случае 0 (ложь) выполняется второй оператор.

person S Praveen Kumar    schedule 06.12.2019
comment
У него есть специальный логический тип, _Bool - person M.M; 06.12.2019
comment
Да. Но он по-прежнему разрешается в целое число (0 или 1). У него нет выделенного логического типа, как в некоторых других языках, таких как Java, который отличается от простого int. - person S Praveen Kumar; 06.12.2019
comment
нет, у него есть специальный логический тип, как и в других языках - person M.M; 06.12.2019