Главная - Литература

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 [143] 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

Пример условия, в котором короткозамкнутое вычисление не спасает от ошибки (Java)

if ( ( ( item / denominator ) > MIN VALUE ) && ( denominator о ) ) ...

Здесь item / denominator вычисляется раньше, чем denominator /= 0. Следовательно, в этом коде происходит ошибка деления на 0.

Язык Java еще более усложняет эту картину, предоставляя «логические» операторы. Логические операторы & и языка Java гарантируют, что все элементы будут вычислены полностью независимо от того, определяется ли истинность или ложность выражения без его полного вычисления. Иначе говоря, в Java такое условие будет безопасно:

Пример условия, которое работает благодаря короткозамкнутому (условному) вычислению (Java)

if ( ( denominator ! = О ) && ( ( item / denominator ) > MIN VALUE ) ) ... A вот такое - нет:

Пример условия, которое не будет работать, потому что короткозамкнутое вычисление не гарантируется (Java)

if ( ( denominator О ) & ( ( item / denominator ) > MIN VALUE ) ) ...

Разные языки используют разные способы вычисления, и случается, что разработчики языка чересчур свободно обращаются с правилами вычисления выражений, поэтому обратитесь к руководству по вашей версии языка, чтобы выяснить, как в нем выполняются эти операции. Еще лучше (поскольку читатель может не обладать вашей сообразительностью) использовать вложенные условия, проясняющие ваши намерения, и не зависеть от порядка обработки выражений и короткозамкнутых вычислений.

Упорядочение числовых выражений

в соответствии со значениями на числовой прямой

Организуйте числовые условия так, чтобы они соответствовали порядку точек на числовой прямой. В общем случае структурируйте выражения так, чтобы сравнения выглядели следующим образом:

MIN ELEMENTS <= i and i MAX ELEMENTS i < MIN ELEMENTS or MAX ELEMENTS < i

Идея в том, чтобы расположить элементы по порядку слева направо, от наименьших к наибольшим. В первой строке MINELEMENTS и MAXELEMENTS - это две граничные точки, и поэтому они расположены по краям выражения. Подразумевается, что переменная / должна находиться между ними, и поэтому она расположена в середине. Во втором примере вы проверяете, находится ли / вне диапазона, поэтому / расположена по краям условия, а MINELEMENTS и MAXELEMENTS - посредине. Этот подход позволяет легко создать визуальное представление сравнения (рис. 19-1):



MIN ELEMENTS <= i and i <= MAX ELEMENTS MIN ELEMENTS Допустимые значения для к MAX ELEMENTS

i < MIN ELEMENTS or MAX ELEMENTS < i MINELEMENTS v > MAX ELEMENTS

«.-,4-

Допустимые значения для i

Рис. 19-1 Пргшеры упорядочения логических условий в соответствии с числовой прямой

Если вы сравниваете значение i только с MIN ELEMENTS, то расположение / зависит от того, каким должно быть / в случае успешной проверки условия. Если предполагается, что / меньше, то условие выглядит так:

while ( i < MIN.ELEMENTS ) ...

Но если / должно быть больше, вы получаете: while ( MIN.ELEMENTS < i ) ...

Этот подход более очевиден, чем такие условия, как: ( i > MIN.ELEMENTS ) and ( i < MAX ELEMENTS )

которые не позволяют читателю визуализировать проверяемое выражение.

Общие принципы сравнения с О

Языки программирования используют О для нескольких целей. Это числовое значение. Это нулевой терминатор в строке. Это пустой указатель. Это значение первого элемента перечисления. Это false в логических выражениях. А посему вам следует писать такой код, чтобы конкретное назначение О было очевидно.

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

while ( !done ) ...

Это неявное сравнение с О допустимо, потому что выполняется в логическом выражении.

Сравнивайте числа с О Хотя в логических выражениях неявное сравнение с О допустимо, числовые выражения следует сравнивать явно. Для чисел пишите:

while ( balance != О ) ... а не:

while ( balance ) ...



В языке С сравнивайте символы с нулевым терминатором С\(У) явно Символы, как и числа, не являются логическими выражениями. Поэтому для символов следует писать:

while ( *charPtr != \0 ) ... а не:

while ( *charPtr ) ...

Эта рекомендация расходится с широко распространенным соглашением языка С по обработке символьных данных (так, как показано во втором примере). Но первый способ усиливает идею, что выражение имеет дело с символьными, а не с логическими данными. Некоторые соглашения С не основываются на максимизации удобства чтения или сопровождения, и это - один из таких примеров. К счастью, весь этот вопрос растворяется в лучах заката, поскольку все больше кода пишется с использованием строк С++ и STL.

Сравнивайте указатели с NULL Для указателей пишите: while ( bufferPtr != NULL ) ...

а не:

while ( bufferPtr ) ...

Как и в случае с символьными данными, эта рекомендация расходится с устоявшимся соглашением языка С, но преимущество в читабельности ее оправдывает.

Общие проблемы с логическими выражениями

Логические выражения содержат еще несколько ловушек, специфичных для некоторых языков программирования:

В С-подобныхязыках, помещайте константы елевой стороны сравнений

В С-подобных языках возникают некоторые специфические проблемы с логическими выражениями. Если время от времени вы набираете = вместо ==, подумайте об использовании соглашения по размещению констант и литералов с левой стороны выражений, например, так:

Пример размещения константы с левой стороны выражения на С++. Это позволит компилятору обнаружить ошибку

if ( MIN.ELEMENTS = i ) ...

В этом выражении компилятор обязан объявить одиночный знак = ошибкой, поскольку недопустимо присваивать какое-нибудь значение константе. А в следующем выражении компилятор, напротив, выдаст только предупреждение, и лишь в том случае, если у вас включены все предупреждения компилятора:

Пример размещения константы с правой стороны выражения на С++. Эту ошибку компилятор может и не обнаружить

if ( i = MIN.ELEMENTS ) ...



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 [143] 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294



0.0104