Условный оператор if... else
Условный оператор реализует структуру выбора. Он имеет такой вид:
if (условие) оператор1 else оператор 2
Если условие оценивается как истинное (ненулевое), выполняется onepamop1, если как ложное (нулевое), выполняется onepamop2. Простейший пример:
if (а > b)
max_ab = a;
else
max_ab = b;
Как было сказано чуть выше, вместо одиночного оператора всегда можно подставить блок из нескольких операторов, заключенный в фигурные скобки. Другими словами, возможна следующая синтаксическая форма:
if (условие)
{опера торы_блока_if)
else
(опера торы_блока_еlsе}
В случае, когда при ложности условия не нужно выполнять никаких действий, а требуется только пропустить операторы блока if, ключевое слово else и соответствующий ему оператор (блок) могут отсутствовать, как в следующем примере:
if (а > b) { // Если а > b, поменять их местами;
temp = а; // в противном случае оставить все, как есть.
а = b;
b = temp;
}
//...Продолжение программы...
В соответствии с правилом суперпозиции можно строить вложенные структуры if...else, например:
if (a > b)
if (a > с)
max_abc = а;
else
max abc = с;
else
if (b > с)
max_abc = b;
else
max_abc = с ;
Эта конструкция всего-навсего определяет наибольшее из трех чисел, но разобраться в ее логике не так-то просто. Кроме того, следует помнить, что если во вложенных условных структурах используются как полные, так и неполные операторы if (без else), то могут возникать неоднозначности. Попробуем, например, переписать предыдущий фрагмент чуть более экономно, заранее присвоив максимуму значение с:
Max_abc = с;
if (a > b)
if (a > c)
max_abc == a;
else
if (b > C) max_abc = b;
К которому из двух первых if относится это else? По задуманной нами логике — к первому, однако компилятор считает по-другому; он разрешает подобные неоднозначности, ставя спорное else в соответствие ближайшему if, т. е. в данном случае второму. В результате все работает неправильно. Чтобы устранить неоднозначность, нужно применить операторные скобки:
max_abc = с;
if (а > b) {
if (а > с)
max_abc = а;
else if (b > с)
max abc = b;
Об условиях в операторе if
Условие оператора if может быть сколь угодно сложным выражением. Можно было бы сказать, что это выражение должно быть “логическим”, но в С нет логического типа данных. Как уже говорилось, выражение считается ложным, если его значением является нуль, и истинным, если значение ненулевое.
Вот несколько примеров условий оператора if:
if (x) DoSomething();
// Если х не равно
// нулю.
if (!x) DoAnotherThing();
// Если х равно нулю.
if (b == с) DoAnotherThing();
// Если b равно с.
if (b != с) DoSomething();
// Если b не равно с.
if ((key = getch()) == 'q') DoQuitO;
// Сохранить код
// клавиши в key
// и проверить, равен
// ли он ' q ' .
#define ERR_FLAG 0х80
// Если бит ERR_FLAG
if (flags & ERR_FLAG) ReportError();
// переменной flags
// установлен.
if (a >= b && a <= c) DoSomething();
// Если а лежит между
// b и с.
Операции отношения (==, !=, <, >= и т. д.) возвращают ненулевой целый результат, если значения операндов удовлетворяют отношению. В большинстве реализации С это 1, но полагаться на это не стоит. Если отношение не удовлетворяется, результатом операции будет нуль.
Обратите внимание на три последних примера. В пятом примере вы можете видеть разницу между присваиванием (=) и отношением равенства (= =). Не забывайте, что в С присваивание является операцией, возвращающей значение.
В шестом примере вы видите поразрядную операцию AND, с помощью которой проверяется состояние отдельного бита переменной flags. В седьмом примере применена логическая операция AND, которая логически перемножает значения двух отношений.

Кстати о флагах и поразрядных операциях. Битовые флаги — довольно распространенный и очень эффективный прием хранения и передачи информации о состоянии какого-то объекта или процесса, хотя и не очень безопасный. Вот примеры манипуляций с флагами:
flags | = ERR_FLAG; // Установка флага операцией OR.
flags &= ~ERR_FLAG; // Сброс флага операцией AND.
flags "= ERR_FLAG; // Переключение флага операцией XOR.