Пособие по практике программирования


Пример 1.12 - часть 3


? child=(!LC&&!RC)?0:(!LC?RC:LC);

Согласитесь, что, только разобрав все возможные варианты сравнений, можно догадаться, что же делает этот фрагмент. Приведенная ниже конструкция длиннее, но значительно проще, потому что возможные варианты видны сразу:

f (LC == 0 && RC == 0)
child = 0; else if (LC == 0)
child = RC; else
child = LC;

Операция ? : хороша только для коротких и простых выражений-, где она может заменить четыре строки if-else одной, как в следующем примере:

max = (а > b) ? а : b;

или даже в таком случае:

printf("The list has %d item%s\n", n, n==1 ? "" : "s");

однако подобная замена все же не является распространенной.


Ясность и краткость — не одно и то же. Часто более ясный код будет и более коротким (как в примере со сдвигом битов), однако он может быть и, наоборот, более длинным (как в примере с if-else). Главным критерием выбора должна служить простота восприятия.

Будьте осторожны с побочными эффектами. Операции типа ++ имеют побочные эффекты: они не только возвращают значение, но еще и изменяют операнд. Эти побочные эффекты иногда могут быть весьма удобны, но они же могут вызвать трудности из-за того, что получение значения и обновление переменной могут происходить не тогда, когда ожидается. В С и C++ порядок выполнения этих побочных эффектов вообще не определен, поэтому нижеприведенное множественное присваивание, скорее всего, будет выдавать неправильный ответ:

? str[i++] = str[i++] = ' ';

Смысл выражения — записать пробел в следующие две позиции строки str. Однако в зависимости от того, когда будет обновляться i, позиция в st r может быть пропущена, и в результате переменная 1 будет увеличена только на 1. Разбейте выражение на два:

str[i++] = ' ';
str[i++] =''.-"';

Даже если в вы ражении содержится только один инкремент, результат может быть неоднозначным:

? array[i++] = i;

Если изначально i имеет значение 3, то элемент массива может принять значение 3 либо 4.

Побочные эффекты есть не только у инкремента и декремента; ввод-вывод — еще один потенциальный источник возникновения закулисных действий.В следующем примере осуществляется попытка прочитать два взаимосвязанных числа из стандартного ввода:

scanf ("' &yr, &profit[yr]);

Выражение неверно, поскольку одна его часть изменяет уг, а другая использует ее. Значение prof it[yr] будет правильным только в том случае, если новое значение уг будет таким же, как и старое. Вы, наверное, думаете, что все дело в порядке вычисления аргументов, однако в действительности проблема здесь в том, что все аргументы scanf вычисляются до того, как эта операция вызывается на выполнение, так что &profit[yr] всегда будет вычисляться с использованием старого значения у г. Проблемы подобного рода могут возникнуть в любом языке программирования. Для исправления достаточно опять же разбить выражение на две части:

scanf("%d", &yr);
scanf("%d", &profit[yr]);

Будьте осторожны с любым выражением, вызывающим побочные эффекты.




- Начало -  - Назад -  - Вперед -