'VÀ' vs '&&' với tư cách là nhà điều hành


298

Tôi có một cơ sở mã nơi các nhà phát triển quyết định sử dụng ANDORthay vì &&||.

Tôi biết rằng có một sự khác biệt về quyền ưu tiên của các nhà khai thác ( &&đi trước and), nhưng với khung đã cho ( chính xác là PrestaShop ) thì rõ ràng đó không phải là một lý do.

Phiên bản bạn đang sử dụng? Có anddễ đọc hơn &&không? Hay là không có sự khác biệt?


1
Lưu ý rằng đó ~là toán tử KHÔNG khôn ngoan bit và không logic. ;-)
Gumbo

2
Vâng tôi biết. Những thói quen xấu :) . Có một điều hơi lạ là trong PHP có 'và', 'hoặc' và 'xor', nhưng không có 'không', phải không?
ts.

1
@ts: câu trả lời đúng ở đây là câu trả lời được cung cấp bởi R. Bemrose stackoverflow.com/questions/2803321/and-vs-as-operator/
trộm

4
! là toán tử không hợp lý
Dao cạo Storm

2
@chiliNUT hoàn toàn đúng. Tại thời điểm đó nó phải có ý nghĩa. Có vẻ như câu trả lời không chính xác đã bị trừng phạt vào thời điểm này :)
doublejosh

Câu trả lời:


664

Nếu bạn sử dụng ANDOR, cuối cùng bạn sẽ bị vấp ngã bởi một cái gì đó như thế này:

$this_one = true;
$that = false;

$truthiness = $this_one and $that;

Bạn muốn đoán những gì $truthinessbằng?

Nếu bạn nói false... bzzzt, xin lỗi, sai!

$truthinessở trên có giá trị true. Tại sao? =độ ưu tiên cao hơn and. Việc thêm dấu ngoặc đơn để hiển thị thứ tự ngầm làm cho điều này rõ ràng hơn:

($truthiness = $this_one) and $that

Nếu bạn đã sử dụng &&thay vì andtrong ví dụ mã đầu tiên, nó sẽ hoạt động như mong đợi và được false.

Như đã thảo luận trong các ý kiến ​​dưới đây, điều này cũng hoạt động để có được giá trị chính xác, vì dấu ngoặc đơn có độ ưu tiên cao hơn =:

$truthiness = ($this_one and $that)

135
+1: điều này nên được làm rõ và rõ ràng trong tài liệu PHP hoặc PHP sẽ thay đổi và ưu tiên tương tự cho các toán tử này hoặc ĐỔI and ormột lần cho tất cả. Tôi đã thấy quá nhiều người nghĩ rằng chúng giống hệt nhau và câu trả lời ở đây là nhiều lời chứng thực hơn.
Marco Demaio

11
Trên thực tế, các ngôn ngữ khác (ví dụ Perl và Ruby) cũng có các biến thể này có cùng mức độ phân biệt ưu tiên, do đó, sẽ không hợp lý khi đi chệch khỏi tiêu chuẩn này (tuy nhiên có thể gây nhầm lẫn cho người mới bắt đầu) bằng cách ưu tiên bằng PHP. Chưa kể khả năng tương thích ngược của hàng tấn ứng dụng PHP.
Mladen Jablanović

23
Mọi người không có khả năng đọc tài liệu cho một ngôn ngữ không làm cho các quyết định của ngôn ngữ đó sai. Như Mladen lưu ý, Perl và Ruby cũng sử dụng các toán tử bổ sung này và với cùng các ưu tiên. Nó cho phép các cấu trúc như $foo and bar(), đó là các phím tắt đẹp cho câu lệnh if. Nếu hành vi bất ngờ (từ tài liệu xấu hoặc không đọc nó) là một lý do không sử dụng thứ gì đó mà chúng ta sẽ không nói về việc sử dụng PHP.
Altreus

2
Tôi đã dành 3 phút để tìm sai dòng: $ this = true , :( và những gì về $ trueiness = ($ this và $ that); nó sẽ tốt hơn cho tôi :)
Dmitriy Kozmenko

6
Tôi đồng ý với Dmitriy - gói đánh giá boolean trong ngoặc đơn giúp làm rõ ý định của mã. Tôi nghĩ rằng toán tử và chức năng của nó khi chúng tồn tại là có giá trị và phù hợp với các ngôn ngữ khác, đó là công việc của lập trình viên để hiểu ngôn ngữ.
Jon z

43

Tùy thuộc vào cách sử dụng, nó có thể cần thiết và thậm chí tiện dụng. http://php.net/manual/en/lingu.operators.logical.php

// "||" has a greater precedence than "or"

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;

// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;

Nhưng trong hầu hết các trường hợp, có vẻ như nhiều thứ thuộc về nhà phát triển hơn, giống như mọi sự cố xảy ra mà tôi đã thấy trong khung CodeIgniter như @Sarfraz đã đề cập.


2
Điều đáng chú ý là "đúng" không bị bỏ qua nếu biểu thức đó là một phần của tuyên bố lớn hơn. Xem xét trường hợp if ($f = false or true) $f = true;- kết quả cuối cùng sẽ $ftrở thành đúng, bởi vì biểu thức đánh giá là đúng tổng thể.
Chris Browne

1
không, bạn chỉ đơn giản ghi đè lên biến sau đó. biểu thức vẫn được đánh giá là false, sau đó bạn ghi đè lên nó bằng true trong dòng tiếp theo.
r3wt

2
Thật ra, anh đã đúng. Đầu tiên, $fđược gán sai - nhưng điều kiện đánh giá là đúng, do đó $fđược ghi đè. Nếu điều kiện được đánh giá là sai, $fsẽ không bao giờ bị ghi đè.
ahouse101

Thật nực cười khi đề nghị các nhà phát triển nên làm theo sở thích của họ. Quên cơn ác mộng của một nhà phát triển khác đang cố gắng duy trì cùng một mã, nhà phát triển đã viết chính mã đó sẽ mắc lỗi ngữ nghĩa trong bất kỳ mã nào được viết bởi vì họ thích andhơn &&, trong đó chỉ andhoạt động như mong đợi trong một số tình huống và &&hoạt động như mong đợi tình huống.
ADTC

13

Để an toàn, tôi luôn liệt kê các so sánh của mình và đưa chúng ra ngoài. Theo cách đó, tôi không phải dựa vào quyền ưu tiên của nhà điều hành:

if( 
    ((i==0) && (b==2)) 
    || 
    ((c==3) && !(f==5)) 
  )

29
Cá nhân tôi nghĩ rằng việc thêm các dấu ngoặc đơn không cần thiết làm cho việc đọc trở nên khó hiểu hơn là chỉ có những gì bạn cần. Ví dụ: tôi nghĩ rằng điều này dễ đọc hơn nhiều: if (($ i == 0 && $ b == 2) || ($ c == 3 && $ f! = 5))
rooby

4
Tôi nghĩ rằng đây là đoạn mã đẹp nhất mà tôi đã xem cả ngày. Làm tốt lắm.
rm-vanda

Vì PHP là ngôn ngữ được diễn giải nên nó sẽ chạy nhanh nếu bạn không sử dụng các khoảng trắng không cần thiết hoặc các dòng mới trên mã của mình. Nếu bạn làm tương tự trên một ngôn ngữ được biên dịch, nó sẽ chỉ mất nhiều thời gian hơn để biên dịch nhưng nó sẽ không có hiệu lực trong thời gian chạy. Tôi không có nghĩa là làm điều đó một lần sẽ đánh dấu một sự khác biệt nhưng trên toàn bộ ứng dụng sử dụng php + javascript đều được viết như ví dụ ... thời gian tải sẽ chắc chắn lớn hơn. Giải thích: Các khoảng trắng và các dòng mới được bỏ qua, nhưng để bỏ qua chúng, chúng phải được kiểm tra. Điều này xảy ra trong thời gian chạy trên các lang được giải thích và khi biên dịch trên một cái được biên dịch.
JoelBonetR

@JoelBonetR nếu bạn đang sử dụng php opcache hoặc tương tự mối quan tâm của bạn về thời gian tải là không liên quan. Tôi hy vọng không ai đang chạy một trang php sản xuất mà không có nó ...
PeloNZ

@PeloNZ để bạn có thể viết bẩn vì dù sao nó cũng sẽ được lưu vào bộ nhớ cache và toàn bộ dự án sẽ chỉ mất thêm một giây để tải khi làm mới, hả? Để làm sạch mã là cho chính bạn và đồng đội của bạn, liên quan đến thời gian chỉ là một điểm mà hầu hết mọi người bỏ qua hoặc đơn giản là không biết.
JoelBonetR

11

Khác với ưu tiên giữa && (&& có độ ưu tiên cao hơn và), một cái gì đó gây nhầm lẫn khi kết hợp với một nhà điều hành ternary. Ví dụ,

$predA && $predB ? "foo" : "bar"

sẽ trả về một chuỗi trong khi

$predA and $predB ? "foo" : "bar"

sẽ trả lại một boolean .


10

andcó quyền ưu tiên thấp hơn =bạn có thể sử dụng nó trong gán điều kiện:

if ($var = true && false) // Compare true with false and assign to $var
if ($var = true and false) // Assign true to $var and compare $var to false

2

Hãy để tôi giải thích sự khác biệt giữa những người khác và người khác -

"&&" và "và" cả hai đều là các phép toán AND logic và chúng thực hiện cùng một thứ, nhưng quyền ưu tiên của toán tử là khác nhau.

Ưu tiên (ưu tiên) của một toán tử chỉ định mức độ "chặt chẽ" của nó liên kết hai biểu thức với nhau. Ví dụ: trong biểu thức 1 + 5 * 3, câu trả lời là 16 chứ không phải 18 vì toán tử nhân ("*") có độ ưu tiên cao hơn toán tử cộng ("+").

Trộn chúng lại với nhau trong một thao tác duy nhất, có thể mang lại cho bạn kết quả bất ngờ trong một số trường hợp tôi khuyên bạn nên luôn sử dụng &&, nhưng đó là lựa chọn của bạn.


Mặt khác, "&" là hoạt động bitwise AND . Nó được sử dụng để đánh giá và thao tác các bit cụ thể trong giá trị số nguyên.

Ví dụ nếu bạn làm (14 & 7) thì kết quả sẽ là 6.

7   = 0111
14  = 1110
------------
    = 0110 == 6

1

Phiên bản bạn đang sử dụng?

Nếu các tiêu chuẩn mã hóa cho cơ sở mã cụ thể mà tôi đang viết mã để chỉ định toán tử nào sẽ được sử dụng, tôi chắc chắn sẽ sử dụng mã đó. Nếu không, và mã ra lệnh nên được sử dụng (không thường xuyên, có thể dễ dàng làm việc xung quanh) thì tôi sẽ sử dụng nó. Nếu không, có lẽ && .

Là 'và' dễ đọc hơn '&&'?

Là nó dễ đọc hơn cho bạn . Câu trả lời là có và không phụ thuộc vào nhiều yếu tố bao gồm mã xung quanh toán tử và người thực sự đọc nó!

| | Có ~ sự khác biệt?

Đúng. Xem toán tử logic cho ||toán tử bitwise cho ~.


0

Tôi đoán đó là vấn đề của hương vị, mặc dù (nhầm lẫn) trộn chúng có thể gây ra một số hành vi không mong muốn:

true && false || false; // returns false

true and false || false; // returns true

Do đó, sử dụng && và || an toàn hơn vì họ có quyền ưu tiên cao nhất. Liên quan đến khả năng đọc, tôi muốn nói rằng các toán tử này là đủ phổ quát.

CẬP NHẬT : Về các ý kiến ​​nói rằng cả hai hoạt động trả về sai ... tốt, thực tế, đoạn mã trên không trả về bất cứ điều gì, tôi xin lỗi vì sự mơ hồ. Để làm rõ: hành vi trong trường hợp thứ hai phụ thuộc vào kết quả của hoạt động được sử dụng. Quan sát cách ưu tiên của các nhà khai thác phát huy tác dụng ở đây:

var_dump(true and false || false); // bool(false)

$a = true and false || false; var_dump($a); // bool(true)

Lý do $a === truelà bởi vì toán tử gán được ưu tiên hơn bất kỳ toán tử logic nào, như đã được giải thích rất rõ trong các câu trả lời khác.


16
Điều này không đúng, tất cả đều trả về false.
Jay

0

Đây là một ví dụ nhỏ:

$a = true;
$b = true;
$c = $a & $b;
var_dump(true === $c);

đầu ra:

bool(false)

Tôi muốn nói loại lỗi đánh máy này có nhiều khả năng gây ra các vấn đề ngấm ngầm (theo cách tương tự như =vs ==) và ít được chú ý hơn so với adn/ rolỗi chính tả sẽ đánh dấu là lỗi cú pháp. Tôi cũng tìm thấy và / hoặc dễ đọc hơn nhiều. FWIW, hầu hết các khung công tác PHP thể hiện sở thích (hầu hết không) chỉ định và / hoặc. Tôi cũng chưa bao giờ gặp phải một trường hợp thực tế, không tranh chấp, nơi nó sẽ có vấn đề.


0

Một ví dụ đẹp khác sử dụng các ifcâu lệnh mà không có =thao tác gán.

if (true || true && false); // is the same as:
if (true || (true && false)); // TRUE

if (true || true AND false); // is the same as:
if ((true || true) && false); // FALSE

bởi vì ANDcó quyền ưu tiên thấp hơn và do đó ||có quyền ưu tiên cao hơn.

Đây là khác nhau trong các trường hợp true, false, falsetrue, true, false. Xem https://ideone.com/lsqovs để biết ví dụ chi tiết.

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.