скобки необходимы, чтобы сначала выполнить присваивание, а затем сравнение с '\n'.
По определению численным результатом вычисления выражения отношения или логического выражения является 1, если оно истинно, и 0, если оно ложно.
Унарный оператор ! преобразует ненулевой операнд в 0, а нуль в 1. Обычно оператор ! используют в конструкциях вида
if (!valid)
что эквивалентно
if (valid == 0)
Трудно сказать, какая из форм записи лучше. Конструкция вида !valid хорошо читается ("если не правильно"), но в более сложных выражениях может оказаться, что ее не так-то легко понять.
Упражнение 2.2. Напишите цикл, эквивалентный приведенному выше or-циклу, не пользуясь операторами && и ||.
2.7 Преобразования типов
Значения типа char
- это просто малые целые, и их можно свободно использовать в арифметических выражениях, что значительно облегчает всевозможные манипуляции с символами. В качестве примера приведем простенькую реализацию функции atoi, преобразующей последовательность цифр в ее числовой эквивалент.
/* atoi: преобразование s в целое */
int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; s[i] = '0' && s[i] = '9'; ++i)
n = 10 * n + (s[i] - '0');
return n;
}
Как мы уже говорили в главе 1, выражение
s[i] -'0'
дает числовое значение символа, хранящегося в s[i], так как значения '0', '1' и пр. образуют непрерывную возрастающую последовательность.
Другой пример приведения char к int связан с функцией lower, которая одиночный символ из набора ASCII, если он является заглавной буквой, превращает в строчную. Если же символ не является заглавной буквой, lower его не изменяет.
/* lower: преобразование c в строчную, только для ASCII */
int lower(int c)
{
if (c = 'A' && c ='Z')
return c +'a'-'A';
else
return c;
}
В случае ASCII эта программа будет работать правильно, потому что между одноименными буквами верхнего и нижнего регистров - одинаковое расстояние (если их рассматривать как числовые значения). Кроме того, латинский алфавит - плотный, т. е. между буквами A и Z расположены только буквы. Для набора EBCDIC последнее условие не выполняется, и поэтому наша программа в этом случае будет преобразовывать не только буквы.
Стандартный заголовочный файл ctype.h, описанный в приложении B, определяет семейство функций, которые позволяют проверять и преобразовывать символы независимо от символьного набора. Например, функция tolower(c) возвращает букву c в коде нижнего регистра, если она была в коде верхнего регистра, поэтому tolower - универсальная замена функции lower, рассмотренной выше. Аналогично проверку
c = '0' && c = '9'
можно заменить на isdigit(c)
Далее мы будем пользоваться функциями из ctype.h.
Существует одна тонкость, касающаяся преобразования символов в целые числа: язык не определяет, являются ли переменные типа char знаковыми или беззнаковыми. При преобразовании char в int может ли когда- нибудь получиться отрицательное целое? На машинах с разной архитектурой ответы могут отличаться. На некоторых машинах значение типа char с единичным старшим битом будет превращено в отрицательное целое (посредством "распространения знака"). На других - преобразование char в int осуществляется добавлением нулей слева, и, таким образом, получаемое значение всегда положительно.
Гарантируется, что любой символ из стандартного набора печатаемых символов никогда не будет отрицательным числом, поэтому в выражениях такие символы всегда являются положительными операндами. Но произвольный восьмибитовый код в переменной типа char на одних машинах может быть отрицательным числом, а на других - положительным. Для совместимости переменные типа char, в которых хранятся несимвольные данные, следует специфицировать явно как signed или unsigned.
Отношения вроде i j и логические выражения, перемежаемые операторами amp;& и ||, определяют выражение-условие, которое имеет значение 1, если оно истинно, и 0, если ложно. Так, присваивание
d = c = '0' && c = '9'
установит d в значение 1, если c есть цифра, и 0 в противном случае. Однако функции, подобные isdigit, в качестве истины могут выдавать любое ненулевое значение. В местах проверок внутри if, while, for и пр. "истина" просто означает "не нуль".
Неявные арифметические преобразования, как правило, осуществляются естественным образом. В общем случае, когда оператор вроде + или * с двумя операндами (бинарный оператор) имеет разнотипные операнды, прежде чем операция начнет выполняться, "низший" тип повышается до "высшего". Результат будет иметь высший тип. В параграфе 6 приложения A правила преобразования сформулированы точно. Если же в выражении нет беззнаковых операндов, можно удовлетвориться следующим набором неформальных правил:
· Если какой-либо из операндов принадлежит типу long double, то и другой приводится к long double.
· В противном случае, если какой-либо из операндов
принадлежит типу double, то и другой приводится к double.
· В противном случае, если какой-либо из операндов принадлежит типу float, то и другой приводится к float.
· В противном случае операнды типов char и short приводятся к int.