2012-01-13 4 views
2

이 코드가 올바른 이유 또는 이유를 설명하십시오. 제 생각에는 p1이 먼저 역 참조되고 다음에 증가하기 때문에 ++ ++ p1 = * p2 ++ 행은 정의되지 않은 동작을합니다.정의되지 않은 동작입니까? 그 이유는 무엇입니까?

int main() 
{ 
    char a[] = "Hello"; 
    char b[] = "World"; 

    char* p1 = a; 
    char* p2 = b; 

    //*++p1 = *p2++; // is this OK? 
    ++*p1 = *p2++; // is this OK? Or this is UB? 

    std::cout << a << "\n" << b; 

    return 0; 
} 
+6

나는 모든 사람들이 아침 그룹화에 대한 질문을 왜 궁금해 임의의'++','*'와'='하나 끔찍하게 복잡하고 어려운 읽기 라인 ... – ereOn

+11

에 당신은 시도해야하는 경우 코드가 끔찍하게 폭발할지, 아니면 묵시록을 일으킬 지 여부를 알아 내고 ** 사용하지 마십시오. 그것이 얼마나 잘 정의되어 있는지에 관계없이, * 좋은 코드가 아닙니다 *. – ssube

+1

읽기 쉽고 투명하지 않은 경우 괜찮지 않습니다. – maligree

답변

9

첫 번째는 괜찮

*++p1 = *p2++ // p1++; *p1 = *p2; p2++; 

두 번째는 C와 UB입니다 ++ 당신은 p1에 의해 두 번 지적 (한 번 때문에 한 번 때문에 할당 증가의) 어떠한 순서가없는 어떤 수정되기 때문에 두 가지 부작용을 구분하는 포인트.

C++ 0x 규칙을 사용하면 설명하고 이해하기가 더 복잡하고 복잡합니다. 만약 당신이 의도적으로 두 번째 것과 같은 표현을 작성한다면, 코드 골프 경쟁이 아니고, 나를 위해 일한다면, C++ 0x에서 합법적이라고해도 해고를 고려하십시오.

C++ 0x에서 합법적인지 모르겠다. 알고 싶지 않습니다. 나는 이런 식으로 낭비하는 뉴런이 너무 적다.

+4

+1 : "스스로 해고 고려하십시오": 그것은 나를 웃게했습니다. 똑똑함은 복잡한 코드 행을 작성하는 것이 아니라 단순한 코드를 작성할 수 있음으로써 입증됩니다. – ereOn

+1

둘째는 C++ 03과 C++ 11 모두에서 UB가 아닙니다. –

+0

@SergeDundich : C++ 표준은 "이전 및 다음 시퀀스 포인트 사이에서 스칼라 객체는 저장된 값을 최대 한 번 표현식 평가로 수정해야합니다"라고 요구합니다. 두 번째 경우는 시퀀스 포인트가없는 단일 표현식이며 동일한 스칼라 값에 두 번 쓰고 있습니다. – 6502

1

정의되지 않은 동작 아니요. 심지어 구현은 또는 으로 정의되지 않았습니다.입니다. (세 용어는 모두 다른 것입니다.)

이 두 줄은 모두 잘 정의되어 있지만 다른 것들을 수행합니다.

*++p1 = *p2++; 

_T1* _p1 = ++p1; 
T2_* p2_ = p2++; 
*_p1 = *p2_; 

그리고

++*p1 = *p2++; 

동등하면

T1& x = *p1; 
__T1_& y = ++x; 
T2_* p2_ = p2++; 
y = *p2_; 

동등 691,363,210
  • T1&

    즉 모든 T1/_T1/__T1_/T2_은,

  • __T1_&++(*p1) 표현의 유형이,

  • _T1*++p1 표현의 유형,
  • T2_*p2++ 표현의 유형이있다, *p1 표현의 유형 귀하의 경우에는 char입니다.

++x 이후 귀하의 경우 xyx에 반환 참조있는 동일한 참조 (*p1 즉) (C++ 기본 유형) -하지만 T1 일부 사용자 정의 유형 될 경우이 사건되지 않을 수도 있습니다 과부하로 operator++().

ADD :

는 분명히 값을 증가하고 완전히 무의미에 다음 할당합니다.

예 - 다른 사람들이 이미 말한 것처럼 코드에 대한 질문이 있습니다. 당신에게 명확하고 독자들에게 명확해야 할 것을 적어 두십시오.

ADD2 :

분쟁 점을 명확히하기 위해 나는 표준을 인용하겠습니다.

ISO/IEC 14882-2003 5.3.2 :

  1. 프리픽스의 피연산자 ++ 1을 추가하여 수정하거나, 그 BOOL 경우 (이러한 사용은 중단된다)를 true로 설정. 피연산자는 수정 가능 숫자 이어야합니다. 피연산자의 유형은 산술 형이거나 완전히 정의 된 객체 유형을 가리키는 포인터이어야한다. 값은 새로운 피연산자 값입니다. 그것은 lvalue입니다. x가 bool 유형이 아닌 경우 표현식 ++ x는 x + = 1과 같습니다.
+0

두 번째 표현식에서 lvalue'* p1'은 시퀀스 포인트가없는 단일 표현식에서 두 번 (증가 및 할당) 변경되었으며 C++에서는 UB입니다. 이 경우 합법적이라고 생각하는 이유는 무엇입니까? – 6502

+0

@ 6502 : "두 번째 표현식에서 lvalue'* p1'을 두 번 변경했습니다."No. Lvalue'* p1'은'operator ++ '에 의해 한 번 변경됩니다. 그 후에 lvalue'++ (* p)'('operator ++ '의 반환 값)는 대입 연산자에 의해 변경됩니다. –

+0

@ 6502 : 'f (++ x, ++ x)'와 같은 두 개의 표현식 사이에 순서 점이 없더라도 그러한 표현식의 평가 순서는 ** 지정되지 않습니다 ** 그럼에도 불구하고 ** 정의되지 않은 동작 **이 될 것입니다. –

관련 문제