Tiếng Nhật ngắn mạch là gì trong ngôn ngữ C?


14

Tôi đã nghe nói về thuật ngữ "ngắn mạch" đang được sử dụng trong C, C ++, C #, Java và nhiều thuật ngữ khác. Điều này có nghĩa là gì và trong kịch bản nào nó sẽ được sử dụng?


6
Có một bài viết Wikipedia về khái niệm: en.wikipedia.org/wiki/Short-circuit_ev Assessment Đây là một tối ưu hóa trong đánh giá của &&nhà điều hành.
wirrbel

1
@wirrbel Tôi tin rằng nó cũng áp dụng cho ||... ít nhất là nó nên.
Radu Murzea

1
@RaduMurzea Thật vậy. Tương phản ||&&để &|thấy sự khác biệt tinh tế. Có một chương trình đơn giản đánh giá 1 || printf("yay");vs 0 || printf("yay");1 | printf("yay");vs 0 | printf("yay");để xem sự khác biệt
wirrbel

Câu trả lời:


35

Đoản mạch trong C là khi một toán tử logic không đánh giá tất cả các đối số của nó.

Lấy ví dụ và &&, khá rõ ràng 0 && WhoCareslà sẽ sai dù nó WhoCareslà gì . Vì điều này, C chỉ bỏ qua việc đánh giá WhoCares. Tương tự như vậy 1 || WhoCares, nó sẽ luôn luôn đúng. Vì điều này, chúng ta có thể viết mã như

CanFireMissiles && FireMissiles()

Bằng cách này, chúng tôi tránh thực hiện một số hoạt động có thể không thể. Nếu chúng ta không thể bắn tên lửa, chắc chắn chúng ta không muốn thử. Điều này thường được sử dụng với con trỏ, đặc biệt là con trỏ tệp.

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

Điều này diễn ra theo nhiều cách hữu ích khác để tránh tính toán không cần thiết

 isFileReady() || getFileReady()

Điều này tránh làm thêm nếu chúng ta không cần.


1
Bất cứ lúc nào, nếu tôi đã trả lời câu hỏi của bạn, bạn có thể chọn hộp kiểm bên cạnh để đánh dấu câu hỏi của bạn như đã trả lời
Daniel Gratzer

7
Tôi không thích CanFireMissiles && FireMissiles(), vì nó khiến tôi nghi ngờ bạn đang lạm dụng ngắn mạch để kích hoạt tác dụng phụ. Tôi cảm thấy như bạn đang che giấu hành động trong một điều kiện. Mã như vậy được viết tốt hơn là if(CanFireMissiles){FireMissiles();}hoặc if(CanFireMissles){didFireMissiles = TryFireMissiles(); if(didFireMissiles){...}}.
Brian

2
Tôi cho rằng việc sử dụng duy nhất là để che giấu các tác dụng phụ. Thường không phải là kiểu "Thổi hồn thành phố" mà những việc như hủy bỏ con trỏ hoặc sử dụng tài nguyên hệ thống cũng được thực hiện theo cách này trong C khá thường xuyên. Xem trang wikipedia, toàn bộ phần đang sử dụng là "Ẩn tác dụng phụ"
Daniel Gratzer

2
@jozefg bạn cũng có thể sử dụng nó để ngăn chặn các hoạt động đắt tiền như IsInCache(value) || IsInDatabase(value)IsInDatabase có thể mất thời gian (đặc biệt nếu sử dụng thiết bị di động và độ trễ mạng là một vấn đề).
mgw854

4

"Đoản mạch" thường đề cập đến " Đánh giá ngắn mạch " là một khái niệm chung, không chỉ riêng về C.

Đánh giá toán tử Boolean từ trái sang phải, vì vậy bất kỳ thuật ngữ nào sẽ hiển thị các thuật ngữ khác không cần thiết đều hữu ích. Vì vậy, bạn có thể kiểm tra một điều kiện loại trừ các điều kiện khác sau này, do đó cho phép đánh giá một phần các hoạt động logic thay vì đánh giá toàn bộ.

Thí dụ:

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.
}

Một ví dụ phức tạp hơn:

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
Đoản mạch ít hơn về tiết kiệm thời gian nhưng nhiều hơn về việc không được đánh giá. Một chức năng không được đánh giá cũng sẽ không có tác dụng phụ nó sẽ được đánh giá.
Pieter B

Bạn biết đấy, điều == 0này không chỉ không cần thiết, nó thực sự có thể khiến một số người nhầm lẫn.
Ded repeatator

3

Đánh giá ciruit ngắn có thể dẫn đến một số phần của một điều kiện không được đánh giá.

Ví dụ:

if (true || f()) { ... }

sẽ không xuất hiện f.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.