2012-11-01 50 views
5

Trong số những điều sau đây, đó là cách ưa thích để làm việc, và tại sao? Có bất kỳ tình huống cụ thể nào trong đó nó tạo ra bất kỳ sự khác biệt nào, giả sử rằng thanh hàm() không lấy giá trị bằng không tại bất kỳ thời điểm nào?Cách thích hợp nhất để gán và kiểm tra biến trong câu lệnh if là gì?

Trường hợp 1: Kiểm tra các giá trị chân lý của cả hai điều kiện

if ((foo = bar()) && foo < 0) 
    error(); 

Trường hợp 2: Kiểm tra chỉ biến

if ((foo = bar()) < 0) 
    error(); 
+0

Đối với những người tìm thấy điều này và đang sử dụng Perl, thành ngữ là 'foo = bar() hoặc error();'. Điều này cũng có thể được thực hiện trong C, nhưng nó không phải là thực tế phổ biến và có thể gây nhầm lẫn: '(foo = bar()) || error(); '- Nhiệm vụ của Perl có ưu tiên cao hơn' || ', nhưng trong C nó là ngược lại. –

+0

@PhilH Nó thường được coi là phong cách xấu để bao gồm các tác dụng phụ có điều kiện như toán hạng bên phải của một hoạt động boolean (MISRA-C 12.4). Và mã của bạn sẽ chỉ hoạt động nếu error() trả về một cái gì đó. Vì vậy, đừng cố gắng trong C. – Lundin

+0

Điểm tốt về yêu cầu trả lại; Tôi cho rằng trong Perl không có kiểm tra và lỗi như vậy() sẽ luôn luôn chạy. –

Trả lời

14

Cách ưa thích giao là để tách chúng:

foo = bar(); 
if (foo < 0) 
    error(); 

Chỉnh sửa: Đây là cách tốt hơn cho cả khả năng đọc và tránh các lỗi, chẳng hạn như trong trường hợp đầu tiên của bạn:

if (foo = bar() && foo < 0) 
    error(); 

Đó có lẽ nên được:

if ((foo = bar()) && foo < 0) 
    error(); 
+0

Bằng cách này có hiệu suất tốt hơn không? Hoặc là nó được ưa thích chỉ để dễ đọc hơn? –

+5

Trong khi tôi không thể cho bạn biết nếu có một sự khác biệt trong bất kỳ trình biên dịch, coder C không nên quan tâm về điều đó. Đây là cách tốt hơn cho cả khả năng đọc và tránh lỗi. (như trong trường hợp đầu tiên OP) – MByD

+0

Có hoàn toàn không có sự khác biệt về hiệu suất. Trong cả hai trường hợp, mã máy sẽ là: excute bar(), lưu trữ kết quả tạm thời ở đâu đó, sau đó lưu nó trong foo, sau đó rẽ nhánh nếu foo nhỏ hơn 0. – Lundin

2

Người đầu tiên là đồng bằng sai. Vì các quy tắc ưu tiên, bạn nhận được:

if (foo = (bar() && foo < 0)) 
    error(); 

thường không phải là những gì bạn mong đợi.

0

Ví dụ đầu tiên hoạt động, nhưng nếu ai đó cố gắng để thay đổi <-<= hoặc >=, nó sẽ nổ tung: cho bar trở về 0, nó sẽ kiểm tra phần đầu tiên của và tuyên bố và sẽ xem xét nó sai, hủy thứ hai kiểm tra, điều này đúng.

Ngoài ra, ví dụ đầu tiên của bạn không làm những gì nó phải làm: nhà điều hành ưu tiên của = là ít hơn &&, vì vậy bạn sẽ có được chuyển nhượng kết quả của & & -operation để foo

Vì vậy, tôi muốn các ví dụ thứ hai.

0

Trong hầu hết các trường hợp không quan trọng. Trường hợp đầu tiên của bạn có một số dự phòng vì vậy tôi muốn đề nghị thứ hai cho sự ngắn ngủi.

Có một số trường hợp mà cách tiếp cận này không đủ tốt, cụ thể trong môi trường nhiều luồng trong đó biến của bạn là tài sản được chia sẻ (đặt hoạt động kiểm tra là &). Trong trường hợp này, truy cập vào biến cần được bảo vệ đúng cách (tức là bằng cách khóa) để tránh các cuộc đua và tham nhũng dữ liệu.

0

Hầu hết các trình biên dịch nếu không phải tất cả sẽ đưa ra cảnh báo nếu bạn cố thực hiện nhiệm vụ trong dấu ngoặc đơn phụ có điều kiện. Tuy nhiên, trong hầu hết các trường hợp, tôi cho rằng các câu lệnh phức hợp ít có thể đọc được như vậy, trong khi Ruby có nghĩa là không phổ biến trong C. Nếu không có lý do sẽ không bao giờ vượt qua đánh giá mã IMO.

Các vấn đề liên quan