2010-12-06 5 views
19

operator =이 시퀀스 포인트가되지 못하는 이유가 있습니까? C와 C++ 둘 다.할당 연산자가 시퀀스 포인트가 아닌 이유는 무엇입니까?

반례에 대해 생각하는 데 어려움이 있습니다.

+0

그러면 컴파일러는 RHS보다 먼저 LHS를 계산해야합니다. 왜 그런 종류의 제한을 만들고 싶습니까? –

+2

'a = b = c = 0; ' – pmg

+7

일반적으로 상황은 ** 시퀀스 포인트가되어야합니다. 시퀀스 포인트가 될 이유가 ** 없습니다 **. 이것이 기본값입니다. –

답변

20

: 일반적으로

는 상황이 에 이유가 시퀀스 포인트가 될 필요가있다. 그들은 이 아닌이 이유가 될 필요가 없습니다. 이것이 기본값입니다.

예를 들어, 단락 동작으로 인해 &&이 시퀀스 포인트 여야합니다. 왼쪽이 거짓이면 오른쪽 으로 평가되어서는 안됩니다. (이것은 단지 최적화와 관련이 없으며, 오른쪽은 부작용을 가질 수 있으며, 또는 왼쪽에 의존하는 것은 ptr && ptr->data 에서처럼 사실입니다.) 따라서 오른쪽이 먼저 평가되어야합니다 오른쪽을 평가해야 하는지를보기 위해

=의 경우이 이유는 존재하지 않습니다. 왜냐하면 양면에 대해 "평가"가 있지만 양측에 나타날 수있는 것에 대해 다른 제한이 있기 때문입니다. 왼쪽은 왼쪽 값이어야합니다 (l). "왼쪽"을 의미하지는 않습니다. btw는 메모리의 위치와 같이 "위치"를 나타냅니다. 임시 또는 문자로 지정할 수 없습니다.) 어느 쪽이 먼저 평가되는지는 중요하지 않습니다. 양 측은 실제 할당 전에 평가됩니다.

+3

+1하지만 시퀀스 포인트가 아니기 때문에'myArray [i ++] = ;가 있고 두 컴파일러 중 하나가 LHS를 "LHS"뒤에서 계산하여 잘못된 답변. 그럼에도 불구하고 까다 롭습니다. –

+0

IIRC 및 FWIW, Java는 여기에 더 많은 보증을 제공합니다. –

+0

단락 동작 자체로 시퀀스 포인트가 필요하지 않습니다. '(((ch = * x ++)! = 0) && (* y ++ = ch))'와 같은 표현식은 &&가 시퀀스 포인트 *를 부과한다는 명시적인 요구 사항에 대해 실행 후까지 x의 증가를 지연시킬 수 있습니다 컴파일러는 x를 증가시키기 전에 '&&'의 왼쪽 피연산자가 0인지 아닌지를 판단 할 수 있기 때문에 표현식의 두 번째 부분의 실제로는 시퀀스 포인트에 의해 금지 된 코드 재배치가 유용하지는 않을 것으로 보이지만 일부 이론적 인 경우에는 그렇게 될 수 있습니다. – supercat

0

(일종의) 연산자 = (이것은 엔지니어에 의해 정의 될 수 있습니다 (사용자 정의 연산자 = 클래스 유형에 대해))는 함수 호출을위한 구문 적 설탕입니다. 결과적으로 함수 호출과 동일한 "시퀀스 포인트"의미를 갖습니다.

우리가 내장 된 유형을 가지고 있다면 좋은 생각입니다.
시퀀스 포인트가 너무 많아서 최적화를 방해하지 않으려 고합니다. 요청에 의해

+2

이것은 C++의 사용자 정의 클래스를위한 함수 호출을위한 문법적 설탕 일뿐입니다. 당신이 그것을 암시하는 동안, 당신이 말한 방식에서 전혀 명확하지 않습니다. –

+6

' "시퀀스 포인트"의미론 "은별로 유용하지 않습니다. 왜냐하면'operator ='에 대한 인수는'='기호의 LHS와 RHS가 될 것이기 때문에 함수 호출은 그들의 주장 - 기능 자체의 평가는 순서 점입니다. –

0

어느 한 쪽을 다른 쪽보다 먼저 평가하지 않아야하는 데에는 여러 가지 이유가 있습니다. 더 흥미로운 질문은 할당 연산자 자체가 수행하기 전에 양측의 평가가 부작용으로 완료되어야하는지 여부입니다. 이러한 요구 사항은 일부 앨리어싱 제한을 완화 할 수 있지만 경우에 따라 컴파일러에 더 많은 작업이 필요하다고 제안합니다. 예를 들어 "foo"와 "bar"는 주소가 중복되는 큰 구조체에 대한 포인터입니다. 문 "* foo = * bar;" 현재 표준에서 정의되지 않은 동작을 나타냅니다. 피연산자의 평가와 할당 사이에 순서 점이 있다면 그러한 진술은 "작동"할 수 있습니다. 이러한 보장은 대입 연산자에 대해 더 복잡한 작업을 필요로하며 실제로 포인터가 겹치지 않더라도 더 크고 느린 코드를 요구합니다.

예 : 위의 선언을 감안할 때

 
unsigned char foo[100]; 
typedef struct {int x, int y;} POINT; 
POINT *p1 = (POINT*)foo; 
POINT *p2 = (POINT*)(&(p1->y)); 

, 나는 다음과 같은 문이 엄격하게 정의 된 행동 표시하고 정의되지 않은 행동을 수반하지 않는 것 같아요.

 
    p1->y = somevalue; // Sets p2->x to somevalue 
    p2->x = somevalue; // Sets p1->y to somevalue 
    *p1 = mystruct;  // Sets p2->x to mystruct.y 
    *p2 = mystruct;  // Sets p1->x to mystruct.x 

이 두 문장 다음 그러나 정의되지 않은 동작이 포함 것 :이 있다면

 
    *p1 = *p2; 
    *p2 = *p1; 

은 등호에서 시퀀스 지점 서명을, 컴파일러는 다른 P1과 P2를 비교 하나에, 또는 것 소스 피연산자를 임시 위치로 복사 한 다음 목적지로 복사하십시오. 그러나 표준은 위의 두 문장이 둘 다 정의되지 않은 행동으로 간주된다는 것을 분명히합니다. 표준은 컴파일러가 겹쳐지지 않는 구조체에 구조체를 복사 할 때 올바르게 작동하는 코드를 생성하도록 요구하지만, 구조체가 겹칠 경우 컴파일러가 수행 할 수있는 것에 대한 제한을 두지 않습니다. 프로세서가 "Frink Rules!"루프를 보내는 컴파일러입니다. 열려있는 모든 TCP 소켓에서 표준을 위반하지 않을 것입니다.

+0

"주소가 겹치는 _ 큰 구조체 ._"예를 들려 줄 수 있습니까? – curiousguy

+0

"The Simpsons"호머 3D 에피소드에서 "Frink rules"문장을 얻었습니까? – ninjalj

+0

@curiousguy : 예를 참조하십시오. – supercat

관련 문제