Что такое «короткое замыкание» в C-подобных языках?

14

Я слышал, что термин «короткое замыкание» используется в C, C ++, C #, Java и многих других. Что это значит и в каком сценарии это будет использоваться?

Фазиль
источник
6
Есть статья в Википедии о концепции: en.wikipedia.org/wiki/Short-circuit_evaluation Это оптимизация в оценке &&оператора.
wirrbel
1
@wirrbel Я верю, что это относится и к ||... по крайней мере, так должно быть.
Раду Мурзеа
1
@RaduMurzea Действительно. Контраст ||и &&чтобы &и |увидеть тонкую разницу. Имейте простую программу оценки 1 || printf("yay");против 0 || printf("yay");и 1 | printf("yay");против, 0 | printf("yay");чтобы увидеть различия
wirrbel

Ответы:

35

Короткое замыкание в C - это когда логический оператор не оценивает все свои аргументы.

Возьмите для примера, и &&это довольно очевидно, что 0 && WhoCaresбудет ложным, несмотря ни на что WhoCares. Из-за этого C просто пропускает оценку WhoCares. То же самое 1 || WhoCares, всегда будет правдой. Из-за этого мы можем написать код

CanFireMissiles && FireMissiles()

Таким образом, мы избегаем выполнения потенциально невозможной операции. Если мы не можем запустить ракеты, мы, конечно, не хотим пытаться. Это обычно используется с указателями, особенно файловыми указателями.

 bool isN(int* ptr, int n){
     return ptr && *ptr == n;
 }

Это приводит к множеству других полезных способов избежать ненужных вычислений.

 isFileReady() || getFileReady()

Это позволяет избежать дополнительной работы, если нам не нужно.

Даниэль Гратцер
источник
1
В любое время, если я ответил на ваш вопрос, вы можете установить флажок рядом с ним, чтобы пометить ваш вопрос как ответ
Даниэль Гратцер
7
Я не люблю CanFireMissiles && FireMissiles(), так как это заставляет меня подозревать, что вы злоупотребляете коротким замыканием, чтобы вызвать побочные эффекты. Я чувствую, что вы прячете действия в условных. Такой код лучше писать как if(CanFireMissiles){FireMissiles();}или if(CanFireMissles){didFireMissiles = TryFireMissiles(); if(didFireMissiles){...}}.
Брайан
2
Я бы сказал, что единственное использование - это скрывать побочные эффекты. Обычно не «Раздувание города», а такие вещи, как разыменование указателя или использование системных ресурсов, также часто выполняются в Си таким способом. Смотрите страницу википедии, весь используемый раздел - «Скрытие побочных эффектов»
Даниэль Гратцер
2
@jozefg, вы также можете использовать его для предотвращения выполнения дорогостоящих операций, например IsInCache(value) || IsInDatabase(value), когда IsInDatabase может занять некоторое время (особенно если использование мобильного устройства и задержка в сети являются проблемой).
mgw854
4

«Короткое замыкание» обычно относится к « оценке короткого замыкания », которая является общей концепцией, а не только специфической для языка C.

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

Пример:

while((x && y) == 1) {
    //This bit will not execute if x is 0 or y is 0 but y won't even be 
    //evaluated due to short circuit evaluation if x is 0.
}

Более сложный пример:

if((a || b || c || d || e || f || g || h || i || j || k) == 1) {
    /* If any of these are equal to 1 the whole expression is equal to 1,
     * thus doesn't it make sense to short circuit evaluate this?
     * Saves a bunch of time.
     */
}
Мировой инженер
источник
8
Короткое замыкание - это не экономия времени, а отсутствие оценки. Функция, которая не оценивается, также не будет иметь побочного эффекта, если бы она была оценена.
Питер Б
Вы знаете, == 0это не только излишне, это может даже запутать некоторых людей.
дедупликатор