왜 '&'가 아닌 '&&'입니까?
왜 &&
바람직 &
하고 ||
바람직 |
합니까?
나는 수년간 프로그래밍을 해 온 누군가에게 물었고 그의 설명은 다음과 같습니다.
예를 들어에서 if (bool1 && bool2 && bool3) { /*DoSomething*/ }
, 등으로 이동하기 전에 true 여야 bool1
하는 테스트 bool2
하려면 true 여야합니다 bool3
. &
대신 단일을 사용하는 경우 모두에 대해 true 여야하더라도 테스트 순서가 없습니다. 다음 줄로 나아가면 어쨌든 중요한가요?
참고 : 나는 유아와 동등한 프로그래밍이고 이것이 심각하거나 긴급한 질문이 아니라는 것을 지적하고 싶습니다. 왜 다른 것들과 반대로 특정 방식으로해야하는지 이해하는 것이 더 중요합니다.
대부분의 경우, &&
및 ||
이상 선호 &
하고 |
이전하기 때문에 평가는 즉시 결과를 알 수있는 바와 같이 취소 즉, 단락이다.
예:
if(CanExecute() && CanSave())
{
}
CanExecute
반환 하면 의 반환 값에 관계없이 false
전체 표현식이됩니다 . 이 때문에 실행되지 않습니다.false
CanSave
CanSave
이것은 다음과 같은 상황에서 매우 편리합니다.
string value;
if(dict.TryGetValue(key, out value) && value.Contains("test"))
{
// Do Something
}
TryGetValue
false
제공된 키가 사전에 없으면를 반환 합니다. 때문에의 단락 특성 &&
, value.Contains("test")
경우에만 실행됩니다 TryGetValue
반환 true
따라서와는 value
아닙니다 null
. 비트 AND 연산자를 &
대신 사용 NullReferenceException
하면 식의 두 번째 부분이 실행되므로 사전에 키를 찾을 수 없으면 if가 표시됩니다.
이와 비슷하지만 더 간단한 예는 다음 코드입니다 (TJHeuvel에서 언급 한대로).
if(op != null && op.CanExecute())
{
// Do Something
}
CanExecute
이 op
아닌 경우에만 실행됩니다 null
. 경우 op
이며 null
, 식의 첫 번째 부분은 ( op != null
)로 평가 false
하고, 나머지의 평가 ( op.CanExecute()
) 스킵된다.
이 외에도에서은, 기술적으로, 그들도, 다른 :
&&
및 ||
에서만 사용할 수있는 bool
반면, &
및 |
모든 정수 계열 형식 (사용할 수 있습니다 bool
, int
, long
, sbyte
그들이 비트 연산자이기 때문에, ...). &
는 IS 비트 AND 연산자와 |
는 IS 비트 OR 연산자.
매우 정확하게 말하자면 C #에서 이러한 연산자 ( &
, |
[및 ^
])를 "논리 연산자"라고합니다 ( C # 사양 , 장 7.11 참조). 이러한 연산자에는 여러 가지 구현이 있습니다.
- 정수의 (
int
,uint
,long
와ulong
, 제 7.11.1)
들은 피연산자 오퍼레이터의 비트 결과를 계산하도록 구현되고, 즉,&
비트 단위 논리 계산하도록 구현이다AND
등등 - 열거 형의 경우 (7.11.2 장) :
기본 형식의 열거 형의 논리적 작업을 수행하도록 구현됩니다. - 부울 및 널 입력 가능 부울 (7.11.3 및 7.11.4 장) :
결과는 비트 단위 계산을 사용하여 계산되지 않습니다. 가능성의 수가 적기 때문에 결과는 기본적으로 두 피연산자의 값을 기반으로 조회됩니다.
두 값 모두 조회에 사용되므로이 구현은 단락되지 않습니다.
이것이 의미하는 바를 명확하게 설명하기 위해 (다른 답변이 암시하더라도-아마도 이해하지 못하는 용어를 사용하십시오).
다음 코드 :
if (a && b)
{
Foo();
}
실제로 이것으로 컴파일됩니다 :
if (a)
{
if (b)
{
Foo();
}
}
다음 코드는 표시된 그대로 정확하게 컴파일됩니다.
if (a & b)
{
Foo();
}
이것을 단락이라고합니다. 일반적으로 항상 &&
그리고 ||
귀하의 조건에서 사용해야 합니다.
보너스 마크 : 하지 말아야 할 한 가지 시나리오가 있습니다. 만약 성능이 결정적인 상황에 있다면 (이것은 나노초 결정적입니다 ) 단락 null
은 분기 / 점프이기 때문에 반드시 (예 : 점검) 단락을 사용하십시오 ; CPU에서 분기 오류가 발생할 수 있습니다. 는 &
보다 훨씬 저렴합니다 &&
. 단락이 실제로 논리를 깰 수있는 시나리오도 있습니다 . 이 답변 을 살펴보십시오 .
Diatribe / Monologue : 가장 행복하게 무시하는 가지 잘못 예측에 대해 앤디 퍼스 (13 년 동안 게임을해온 사람) 인용 : "이것은 사람들이 갈 필요가 있다고 생각하는 수준이 낮을 수도 있지만 잘못되었을 것입니다. 프로그래밍하는 하드웨어가 지점을 어떻게 처리 할 수 있는지 이해 대부분의 프로그래머가 re : death of a 1,000 cuts보다 훨씬 더 감사 할 것입니다. "
- 게임 개발자 (및 극단적 인 실시간 조건에서 작업하는 다른 사람들)는 예측 변수에 더 적합하도록 논리를 재구성하는 것까지 진행합니다. 디 컴파일 된 mscorlib 코드에도 이러한 증거가 있습니다.
- .NET이 이러한 유형의 것을 차단한다고해서 중요하지 않다는 의미는 아닙니다. 브랜치 잘못 예측은 60Hz에서 엄청나게 비싸다. 또는 10,000 요청 / 초
- 인텔은 잘못된 예측 위치를 식별 할 수있는 도구가 없거나 Windows에 이에 대한 성능 카운터가 없거나 문제를 설명 할 단어가 없습니다.
- 낮은 수준과 아키텍처에 대한 무지가 자신을 잘 아는 사람을 만들지는 않습니다.
- 작업중인 하드웨어의 한계를 항상 이해하십시오.
다음은 비신자에 대한 벤치 마크입니다. https://gist.github.com/1200737에 영향을 미치는 스케줄러를 완화하기 위해 RealTime / High에서 프로세스를 실행하는 것이 가장 좋습니다.
논리 연산자 ( ||
및 &&
)와 비트 연산자 ( |
및 &
).
논리 연산자와 비트 연산자의 가장 중요한 차이점은 논리 연산자는 두 개의 부울을 취하고 부울을 생성하는 반면 비트 연산자는 두 개의 정수를 취하고 정수를 생성한다는 것입니다 (참고 : 정수는 int뿐만 아니라 모든 정수 데이터 유형을 의미 함).
반복적으로 비트 단위 연산자는 비트 패턴 (예 : 01101011)을 가져와 각 비트에서 비트 단위 AND / OR을 수행합니다. 예를 들어 두 개의 8 비트 정수가있는 경우 :
a = 00110010 (in decimal: 32+16+2 = 50)
b = 01010011 (in decimal: 64+ 16+2+1 = 83)
----------------
a & b = 00010010 (in decimal: 16+2 = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)
논리 연산자는 다음에서만 작동합니다 bool
.
a = true
b = false
--------------
a && b = false
a || b = true
둘째, true와 false가 각각 1과 0에 해당하기 때문에 bool에 비트 연산자를 사용하는 것이 종종 가능하며, true를 1로, false를 0으로 변환하면 비트 연산을 수행 한 다음 0이 아닌 값을 변환합니다 true로, 0에서 false로; 논리 연산자를 방금 사용한 경우 결과가 동일하게됩니다 (연습을 위해 이것을 점검하십시오).
또 다른 중요한 차이점은 논리 연산자가 단락 되었다는 것 입니다. 따라서 일부 서클에서 [1] 사람들은 종종 다음과 같은 일을하는 것을 보게됩니다.
if (person && person.punch()) {
person.doVictoryDance()
}
어떤로 변환 : "사람이 (즉, null이 아닌)이있는 경우, 그에게 / 그녀에게 펀치를 시도하고 펀치가 (사실 즉, 반환) 성공하면, 다음 승리의 춤을" .
비트 연산자를 대신 사용했다면 다음과 같습니다.
if (person & person.punch()) {
person.doVictoryDance()
}
에 변환합니다 : "사람이 존재하는 경우 (즉, null이 아닌)과 펀치 (사실, 즉 반환), 다음 승리의 춤을 성공한다" .
단락 된 논리 연산자에서 널 (null) 인 person.punch()
경우 코드가 전혀 실행되지 않을 수 있습니다 person
. 실제로,이 특정한 경우에, 두 번째 코드는 사람이 null인지 여부에 관계없이 person
호출하기 때문에 널 (null) 인 경우 널 참조 오류를 생성합니다 person.punch()
. 올바른 피연산자를 평가하지 않는 이러한 동작을 단락 이라고 합니다.
[1] 일부 프로그래머는 부작용이있는 함수 호출을 if
표현식 안에 넣는 것에 대해 혼란 스러울 수 있지만, 다른 프로그래머에게는 일반적이고 유용한 관용구입니다.
비트 연산자는 한 번에 32 비트에서 작동하기 때문에 (32 비트 시스템을 사용하는 경우) 예를 들어, 여러 조건을 비교해야하는 경우보다 우아하고 빠른 코드로 이어질 수 있습니다.
int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;
Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;
Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;
Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;
CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;
// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`
논리 연산자를 사용하여 동일한 작업을 수행하려면 어색한 비교가 필요합니다.
Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;
Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;
Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;
CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch = bar.rules.can_punch && person.can_punch,
cloc1.usable_abilities.can_kick = bar.rules.can_kick && person.can_kick,
cloc1.usable_abilities.can_drink = bar.rules.can_drink && person.can_drink,
cloc1.usable_abilities.can_sit = bar.rules.can_sit && person.can_sit,
cloc1.usable_abilities.can_shoot_guns = bar.rules.can_shoot_guns && person.can_shoot_guns,
cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
cloc1.usable_abilities.can_talk = bar.rules.can_talk && person.can_talk;
bool cloc2.usable_abilities.can_punch = military.rules.can_punch && person.can_punch,
cloc2.usable_abilities.can_kick = military.rules.can_kick && person.can_kick,
cloc2.usable_abilities.can_drink = military.rules.can_drink && person.can_drink,
cloc2.usable_abilities.can_sit = military.rules.can_sit && person.can_sit,
cloc2.usable_abilities.can_shoot_guns = military.rules.can_shoot_guns && person.can_shoot_guns,
cloc2.usable_abilities.can_talk = military.rules.can_talk && person.can_talk,
cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;
비트 패턴과 비트 연산자가 사용되는 전형적인 예는 Unix / Linux 파일 시스템 권한입니다.
다음의 경우 :
if (obj != null && obj.Property == true) { }
예상대로 작동합니다.
그러나:
if (obj != null & obj.Property == true) { }
잠재적으로 null 참조 예외가 발생할 수 있습니다.
짧고 간단한
1 && 2
= TRUE
때문에
1 = 참 (비 - 제로) C에서
2 = 참 (비 - 제로)에서 C
true
ANDS 논리적으로 true
에주고 true
.
그러나
1 & 2
이진에서 1 = 0001 2 이진에서 0010
이므로 = 0 = false
0001 AND는 0010과 비트 단위로 10 진수로 0000 = 0을 제공합니다.
Likewise for || and | operators too...!
&&
is the short circuit version of &
.
If we are evaluating false & true
, we already know from looking at the first argument that the result will be false. The &&
version of the operator will return a result as soon as it can, rather than evaluate the whole expression. There is also a similar verion of the |
operator, ||
.
if (list.Count() > 14 && list[14] == "foo")
is safe
if (list.Count() > 14 & list[14] == "foo")
would crash if the list doesn't have the right size.
C# Operators should explain why:
Essentially having two &
's or |
's means that it is a conditional rather than a logical, so you can tell the difference between the two.
& Operator has an example of using one &
.
OK, on face value
Boolean a = true;
Boolean b = false;
Console.WriteLine("a({0}) && b({1}) = {2}", a, b, a && b);
Console.WriteLine("a({0}) || b({1}) = {2}", a, b, a || b);
Console.WriteLine("a({0}) == b({1}) = {2}", a, b, a == b);
Console.WriteLine("a({0}) & b({1}) = {2}", a, b, a & b);
Console.WriteLine("a({0}) | b({1}) = {2}", a, b, a | b);
Console.WriteLine("a({0}) = b({1}) = {2}", a, b, a = b);
produce the same answer. However, as you showed, if you have a more complex question so:
if (a and b and c and d) ..
If a
is not true and maybe b
is a function where it has to go off, connect to something, get this, do that, make a decision.. why bother? Waste of time, you know it's already failed. Why make the machine go off and do extra pointless work?
I've always used &&
because I put the most likely to fail first, ergo, less calculations before moving on when there is no point. If there is no way to predict less likely choices, such as you have a boolean to limit output of data, something like:
if (limit && !MyDictionary.ContainsKey("name"))
continue;
If it's not limit
, don't bother checking for the key, which could take longer..
When used in a logical expression such as an if statement &&
preferable because it will stop evaluating expressions as soon as the first false result is encountered. This is possible because a false value will cause the entire expression to be false. Similarly (and again in logical expressions) ||
is preferable because it will stop evaluating expressions as soon as it encounters a true expression because any true value will cause the entire expression to be true.
If however the expressions being or-ed or and-ed together have side effects, and you want all of these to happen as a result of your expression (regardless of the outcome of the logical expression), then &
and |
could be used. Conversely, the &&
and ||
operators can be useful as guards against unwanted side-effects (such as a null pointer causing an exception to be thrown).
The &
and |
operators can also be used with integers and in this case they produce an integer result which is the two operands and-ed or or-ed together at the bit level. This can be useful when an integer value's binary bits are used as an array of true and false values. To test whether a certain bit is on or off, a bit-mask is bitwise and-ed with the value. To turn a bit on, the same mask can be bitwise or-ed with the value. Finally to turn a bit off, the bitwise complement (using ~
) of a mask is bitwise and-ed with the value.
int a = 0; // 0 means all bits off
a = a | 4; // set a to binary 100
if ((a & 4) != 0) {
// will do something
}
a = a & (~4) // turn bit off again, a is now 000
In languages other than C#, care must be taken with the logical versus bitwise modes of & and |. In the code above, the if
statement's conditional expression (a & 4) != 0
is a safe way to express this condition, but in many C like languages, conditional statements can simply treat zero integer values as false and non-zero integer values as true. (The reason for this relates to the conditional branch processor instructions available, and their relationship to the zero flag that is updated after every integer operation.) So the ìf
statement's test for zero can be removed and the condition could be shortened to (a & 4)
.
This could cause confusion and maybe even problems when expressions combined using the bitwise and operator return values that don't have bits that line up. Consider the following example where the side-effects of two functions are desired, before checking that they were both successful (as defined by them returning a non-zero value):
if (foo() & bar()) {
// do something
}
In C, if foo()
returns 1 and bar()
returns 2, the "something" won't be done because 1 & 2
is zero.
C# requires conditional statements like if
to have a boolean oeprand, and the language doesn't allow an integer value to be cast to a boolean value. So the code above would generate compiler errors. It would more correctly be expressed as follows:
if (foo() != 0 & bar() != 0) {
// do something
}
If you are an old-timer C programmer, be careful. C# has really surprised me.
MSDN says for the |
operator:
Binary | operators are predefined for the integral types and bool. For integral types, | computes the bitwise OR of its operands. For bool operands, | computes the logical OR of its operands; that is, the result is false if and only if both its operands are false.
(Emphasis is mine.) Boolean types are handled specially, and in this context the question only starts to make sense, and the difference is, as other already expained in their answers:
&&
and||
are short-circuiting.&
and|
evaluate both operands.
and what's preferable depends on many things like side-effects, performance and code readability, but generally the short-circuiting operators are preferable also because they are better understood by people with a similar background like me.
The reason is: I would argument like this: Since there is no real boolean type in C, you could use the bitwise operator |
and have its result evaluated as truthy or falsy in an if condition. But this is the wrong attitude for C#, because there is already a special case for boolean types.
It's important, because if the cost of evaluation of bool2 (for instance) is high but bool1 is false, then you've saved yourself a fair bit of computation by using && over &
Because &&
and ||
are used for flow control just like if/else
are. It isn’t always about conditionals. It is perfectly reasonable to write as a statement, not as an if
or a while
conditional, the following:
a() && b() && c() && d();
or even
w() || x() || y() || z();
It’s not just that it those are easier to type than the equivalent if/else
versions; they are also much easier to read and understand.
&& and & mean two very different things and give you two different answers.
1 && 2
yields 1 ("true")
1 & 2
yields 0 ("false")
&&
is a logic operator -- it means "true if both of the operands are true"
&
is a bitwise comparison. It means "tell me which of the bits are set in both of the operands"
Quickest (and slightly dumbed down) way to explain this to people who do not NEED to know the exact operations of the code when doing this is
&& is doing a check on each of those conditions Until it finds a false and returns the entire outcome as false
|| is doing a check on each of those conditions Until it finds a true and returns the entire outcome as true.
& is doing MATHS based apon BOTH/ALL the conditions and dealing with the outcome.
| is doing MATHS based apon BOTH/ALL the conditions and dealing with the outcome.
I've never come across a point where I have needed to use & or | within an if statement. I mostly use it for cutting up Hexadecimal values into its component colours using bitwise shift.
EG:
r = fullvalue >> 0xFF & 0xFF;
g = fullvalue >> 0xF & 0xFF;
b = fullvalue & 0xFF;
Within this operation "& 0xFF" is forcing to only look at of the binary value. I have not personally found a use for | yet though.
Simply,
if exp1 && exp2
if exp1 is flase
don't check exp2
but
if exp1 & exp2
if exp1 is false
Or true
check exp2
and rarely people use &
because they rarely want to check exp2 if exp1 is false
참고URL : https://stackoverflow.com/questions/7331686/why-and-not
'IT story' 카테고리의 다른 글
Sublime 3-기능 Goto 정의를위한 키 맵 설정 (0) | 2020.06.24 |
---|---|
EC2 인스턴스 복제 (0) | 2020.06.24 |
SVG 파일에서 변환 제거 (0) | 2020.06.24 |
조상이 jQuery를 사용하여 클래스를 가지고 있는지 확인하십시오. (0) | 2020.06.24 |
iOS : 포인트가 rect 안에 있는지 확인 (0) | 2020.06.24 |