문제

ANSI 표준입니다 위임 논리 연산자는 C 또는 C ++에서 단락되어야합니까?

나는 당신의 코드 가이 작업이 짧은 회로에 의존해서는 안된다는 K & R 책을 기억하기 때문에 혼란스러워합니다. 누군가가 표준에서 논리 작전이 항상 단락 된 위치를 지적 할 수 있습니까? 나는 주로 C ++에 관심이 있습니다. C에 대한 답변도 좋을 것입니다.

또한 평가 순서가 엄격하게 정의되지 않았다는 것을 읽지 않으므로 코드 내에서 함수가 특정 순서로 의존하지 않거나 가정하지 않아야합니다. 진술의 끝까지 모든 참조 된 함수 호출되었지만 컴파일러는 가장 효율적인 순서를 선택할 수있는 자유가 있습니다.

표준은이 표현의 평가 순서를 나타 냅니까?

if( functionA() && functionB() && functionC() ) cout<<"Hello world";
도움이 되었습니까?

해결책

예, 운영자에게는 단락 및 평가 순서가 필요합니다. || 그리고 && C 및 C ++ 표준 모두에서.

C ++ 표준은 말합니다 (C 표준에는 동등한 조항이 있어야 함) :

1.9.18

다음 표현의 평가에서

a && b
a || b
a ? b : c
a , b

이 표현에서 연산자의 내장 의미를 사용하고 첫 번째 표현식의 평가 후 시퀀스 지점이 있습니다. (12).

C ++에는 추가 함정이 있습니다. 단락이 있습니다. 아니다 오퍼레이터를 과부하시키는 유형에 적용하십시오 || 그리고 &&.

각주 12 :이 단락에 표시된 연산자는 5 항에 설명 된 바와 같이 내장 연산자입니다.이 연산자 중 하나가 유효한 컨텍스트에서 과부하 (13 항)가 사용자 정의 연산자 함수를 지정하면 표현이 지정된 표현이 지정됩니다. 기능 호출 및 오페라는 인수 목록을 형성합니다. 그들 사이에 묵시적 시퀀스 지점이 없다.

매우 구체적인 요구 사항이 없다면 일반적으로 이러한 연산자를 C ++에 과부하하는 것이 좋습니다. 이를 수행 할 수는 있지만 다른 연산자 가이 연산자를 과부하시키는 유형으로 인스턴스화하는 템플릿을 통해 간접적으로 사용되는 경우 다른 사람들의 코드에서 예상되는 동작을 중단 할 수 있습니다.

다른 팁

단락 평가 및 평가 순서는 C 및 C ++에서 의무적 인 의미 표준입니다.

그렇지 않다면 이와 같은 코드는 일반적인 관용구가 아닙니다.

   char* pChar = 0;
   // some actions which may or may not set pChar to something
   if ((pChar != 0) && (*pChar != '\0')) {
      // do something useful

   }

부분 6.5.13 논리 및 연산자 C99 사양의 (PDF 링크) 말한다

(4). Bitwise Binary & Operator와 달리 && 운영자는 왼쪽에서 오른쪽으로 평가를 보장합니다. 첫 번째 피연산자 평가 후 시퀀스 지점이 있습니다. 첫 번째 피연산자가 0과 동일하면 두 번째 피연산자는 평가되지 않습니다.

마찬가지로, 섹션 6.5.14 논리 또는 연산자 말한다

(4) 비트와 달리 | 연산자, || 운영자는 왼쪽에서 오른쪽으로 평가를 보장합니다. 첫 번째 피연산자 평가 후 시퀀스 지점이 있습니다. 첫 번째 피연산자가 0과 비교 한 경우, 두 번째 피연산자는 평가되지 않습니다.

C ++ 표준에서도 비슷한 문구를 찾을 수 있습니다. 이 초안 사본에서 섹션 5.14를 확인하십시오. Checkers가 다른 답변에 기록한 것처럼, && 또는 ||를 재정의하는 경우, 두 피연산자는 정기적 인 기능 호출이되므로 평가되어야합니다.

그렇습니다. (평가 순서와 단락 모두). 예제에서 모든 함수가 true를 반환하면 호출 순서는 functiona에서 엄격하게 functionb에서 function으로 이어집니다. 이런 식으로 사용됩니다

if(ptr && ptr->value) { 
    ...
}

쉼표 운영자에게도 동일합니다.

// calls a, then b and evaluates to the value returned by b
// which is used to initialize c
int c = (a(), b()); 

하나는 왼쪽과 오른쪽 피연산자 사이에 말합니다 &&, ||, , 그리고 첫 번째와 두 번째/세 번째 피연산자 사이 ?: (조건부 연산자)는 "시퀀스 포인트"입니다. 부작용은 그 시점 이전에 완전히 평가됩니다. 그래서 이것은 안전합니다.

int a = 0;
int b = (a++, a); // b initialized with 1, and a is 1

쉼표 연산자는 사물을 분리하는 데 사용되는 구문 쉼표와 혼동되어서는 안됩니다.

// order of calls to a and b is unspecified!
function(a(), b());

C ++ 표준이 말합니다 5.14/1:

&& 운영자 그룹은 왼쪽에서 오른쪽으로. 피연산자는 모두 암시 적으로 유형 BOOL (4 항)으로 변환됩니다. 두 피연산자가 모두 참이고 그렇지 않으면 결과는 사실입니다. &, &&와 달리 왼쪽에서 오른쪽으로 평가합니다. 첫 번째 피연산자가 False 인 경우 두 번째 피연산자는 평가되지 않습니다.

그리고에서 5.15/1:

|| 운영자 그룹은 왼쪽에서 오른쪽으로 그룹화합니다. 피연산자는 모두 암시 적으로 bool로 변환됩니다 (4 항). 피연산자 중 하나가 참이면 사실이 반환되고 그렇지 않으면 거짓이됩니다. |, ||와 달리 왼쪽에서 오른쪽으로의 평가를 보장합니다. 또한, 제 1 피연산자가 True로 평가되면 두 번째 피연산자는 평가되지 않습니다.

그것은 그 옆에 다음과 같이 말합니다.

결과는 bool입니다. 두 번째 표현이 평가되기 전에 임시 (12.2)의 파괴를 제외한 첫 번째 표현의 모든 부작용은 발생합니다.

그 외에도 1.9/18 말한다

각 표현의 평가에서

  • a && b
  • a || b
  • a ? b : C
  • a , b

이 표현식에서 연산자의 내장 의미 (5.14, 5.15, 5.16, 5.18)를 사용하면 첫 번째 표현식을 평가 한 후 시퀀스 지점이 있습니다.

좋은 오래된 K & R에서 바로 :

C를 보장합니다 && 그리고 || 왼쪽에서 오른쪽으로 평가됩니다. 곧 이것이 중요한 경우를 보게 될 것입니다.

매우 조심하십시오.

기본 유형의 경우 바로 가기 연산자입니다.

그러나이 연산자를 자신의 클래스 또는 열거 유형에 대해 정의하면 바로 가기가 아닙니다. 이러한 다른 상황에서 사용의 의미 차이로 인해 이러한 연산자를 정의하지 않는 것이 좋습니다.

operator && 그리고 operator || 기본 유형의 경우 평가 순서가 왼쪽에서 오른쪽으로 오른쪽으로 나타납니다 (그렇지 않으면 단락은 어렵습니다 :-) 그러나 정의하는 과부하 된 연산자의 경우 기본적으로 방법을 정의하는 데있어 구문 설탕이므로 매개 변수의 평가 순서가 정의되지 않았습니다.

위키 백과를 신뢰한다면 :

[&& 그리고 ||]는 비트 현행 운영자와 의미 적으로 구별됩니다. 결과가 왼쪽에서 단독으로 결정될 수있는 경우 오른쪽 피연산자를 평가하지 않기 때문입니다.

http://en.wikipedia.org/wiki/c_(programming_language)#characteristics

당신의 질문은 이어집니다 C ++ 연산자 우선 순위 그리고 연관성. 기본적으로, 여러 연산자와 괄호가없는 표현식에서, 컴파일러는이 규칙에 따라 표현식 트리를 구성합니다.

우선 순위에, 당신이 같은 것이있을 때 A op1 B op2 C, 당신은 물건을 그룹화 할 수 있습니다 (A op1 B) op2 C 또는 A op1 (B op2 C). 만약에 op1 보다 우선 순위가 높습니다 op2, 당신은 첫 번째 표현을 얻을 수 있습니다. 그렇지 않으면 두 번째를 얻을 수 있습니다.

연관성을 위해, 당신이 같은 것을 가지고있을 때 A op B op C, 당신은 다시 Thins를 그대로 그룹화 할 수있었습니다 (A op B) op C 또는 A op (B op C). 만약에 op 연관성을 남겼습니다. 우리는 첫 번째 표현으로 끝납니다. 그것이 올바른 연관성을 가지고 있다면, 우리는 두 번째로 끝납니다. 이것은 또한 동일한 우선 순위 수준의 운영자에게도 작동합니다.

이 특별한 경우 && 보다 우선 순위가 높습니다 ||, 표현은 다음과 같이 평가 될 것입니다 (a != "" && it == seqMap.end()) || isEven.

순서 자체는 표현식 트리 형태의 "왼쪽에서 오른쪽"입니다. 그래서 우리는 먼저 평가할 것입니다 a != "" && it == seqMap.end(). 그것이 사실이라면 전체 표현이 사실입니다. 그렇지 않으면 우리는 isEven. 이 절차는 물론 왼쪽-서블 프레스 내부에서 재귀 적으로 반복됩니다.


흥미로운 tidbits이지만 우선 순위의 개념은 수학 표기법에 뿌리를두고 있습니다. 같은 일이 발생합니다 a*b + c, 어디 * 보다 우선 순위가 높습니다 +.

더 흥미롭고 모호한, 불안정한 표현을 위해 A1 op1 A2 op2 ... opn-1 An, 모든 연산자가 동일한 우선 순위를 갖는 경우, 우리가 형성 할 수있는 이진 발현 트리의 수는 소위 호출에 의해 주어집니다. 카탈로니아어 번호. 큰 경우 n, 이것들은 매우 빠르게 자랍니다. 디

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top