2013-07-03 3 views
2

: 순서 사이왜 v [i] = i ++가 C에서 정의되지 않은 동작입니까? ACCU의 과부하 # 115에 흥미로운 기사 읽기

당신이 참여 변수의 상태에 대해 어떤 가정을 할 수 없습니다 포인트 : "악마는 코의 날아 월"나는 저자가 말하는 발견 . 이는 C에서 다른 언어와 달리 다음과 같은 표현식은 정의되지 않은 동작을 초래 함을 의미합니다.

v [i] = i ++;

때문에 C

에서 일련의 지점을 나타내지 않는 할당 연산자

사람이 여기 UB을 의미 자세한 추론 무엇을 설명 할 수 있습니까? 두 시퀀스 포인트 사이에 동일한 변수에 두 번 이상 쓰는 문제가있을 것이라고 생각했는데, 여기에는 v [i] 앨리어싱의 가능성을 제외하고는 볼 수 없습니다 ...

+1

도움이 될만한 정보가 있습니다. http://stackoverflow.com/questions/13744507/why-is-i-vi-undefined –

+0

[(i = i ++ + ++ i, i = i ++ 등 ...)이 정의되지 않은 동작을 설명 할 수 있습니까? ] (http://stackoverflow.com/questions/949433/could-anyone-explain-these-undefined-behaviors-iiiii-etc) –

+0

단락에서는 왜 "시퀀스 포인트 사이에 어떤 가정을 할 수 없는지 설명합니다. 관련 변수의 상태 "와 v [i]는'i'가 어떤 특별한 의미있는 값을 가질 것이라고 가정합니다. –

답변

3

중간에 시퀀스 포인트없이 한 번 이상 변수를 수정하면 정의되지 않은 동작이 발생합니다. 그러나 수정할 값을 결정하기 위해 변수의 값이 인 경우에만에 액세스해야한다는 추가 요구 사항이 있습니다. 여기가 배열 인덱싱 i의 값에 액세스

v[i] = i++; 

을 허용하지 변형이 i (i++)로 이루어지고와 무관 번째 요구 사항이다. 두 액세스 사이에 중간에 시퀀스 포인트가 없으므로 이것은 정의되지 않은 동작입니다.

+1

실제로 공식적인 요구 사항은 "이전 값 은 * 저장 될 값을 결정하기 위해 읽기 전용이어야합니다 *"입니다. * 저장된 * * 수정되지 *. 그리고 불행히도이 요구 사항은 좀 더 까다로운 경우에 해석 될 수 있습니다. 예를 들어 배열'a'의 초기 값이 {0, 1, 2, 3, 4 인 경우'a [a [i]] = i와 같은 표현식이 정의되거나 정의되지 않아야하는지 여부가 즉시 명확하지 않습니다. ...}'. 이것은 시퀀싱 규칙이 최신 C 및 C++ 사양 (C11, C++ 11)에서 완전히 다시 설계된 이유 중 하나입니다. – AnT

+0

@AndreyT 특히 C++ 11 표준을 살펴보면 필자의 경우 가장 관련있는 절은 1.8.15라고 생각합니다. 특히 "스칼라 객체의 부작용이 동일한 스칼라 객체의 값을 사용하는 값 ​​계산과 관련하여 순서가 지정되지 않은 경우 동작은 정의되지 않습니다." 나는 "스칼라 객체의 부작용"으로 "i ++"로, "같은 scalr 객체의 값을 사용하는 값 ​​계산"으로 "v [i]"로 해석합니다. – abigagli

3

읽기가 있습니다 동일한 시퀀스 포인트 내에서 i의 쓰기가 가능합니다. 즉, 주소 v[i]을 계산 한 후 i++이 i를 OR 할 수 있습니다. 사실,이 동작은 정의되지 않았기 때문에 컴파일러는이 문을 도달 할 수 없다고 가정하고 제거 할 수 있습니다. (또는 악마가 코 등으로 날아 오르게하십시오)

5

글쓰기 만의 것이 아닙니다. 읽기는 변수의 이전 값 또는 새 값을 읽는지 여부를 모르는 경우에도 역할을합니다. 이 경우 v[i]이 이전 값인 i 또는 i의 새 값을 참조하는지 여부를 알 수있는 방법이 없습니다.

예를 들어, 식 v[i] = i++는 과제 수행

  1. 로 해석 될 수 있습니다 v[i] = i
  2. 증가를 i

또는, 또는,

  1. 로 해석 될 수 이전 값인가져 오기: 쉽게 볼 수 있듯이, 코드의 행동이 그것을 해석 방법에 따라 변경 v[i] = i_old

: i_old = i

  • 은 증가 i
  • 은 할당을 수행합니다.이것은 가능한 두 가지 가능한 시나리오의 예입니다.

    그러나 언어는 제한된 다양한 시나리오에 대한 동작을 제한하지 않습니다. 대신에 언어는 그 행동이 정의되지 않았다고 말합니다. 다른 말로하면, 컴파일러는이 코드를 "예측 가능한"방식으로 해석하는 것을 거부 할 수 있습니다.

  • +0

    이 예제는 정말 유용하며, Praetorian만큼 좋기 때문에 하나 이상의 답변을 수락 할 수 있기를 바랍니다.하지만 저는이 옵션을 명시 적으로 언급했기 때문에 "변수의 값 오직 수정 된 가치를 결정하기 위해 접근해야만합니다. "내가 찾고 있던 구체적인 추론이 무엇인지 알려주었습니다. 고마워요. – abigagli

    +0

    @abigagli : 문제 없습니다. 올바른 문구가 실제로 "저장된 * 값을 결정하기 위해 액세스 됨"이라는 것을 명심하십시오. 또한, 몇 가지 추가 정보에 대한 Praetorian의 답변에 대한 내 의견을 참조하십시오. – AnT