++ 연산자에 대한 C와 C++의 차이
저는 어떤 코드를 가지고 장난을 치다가 "왜"인지 이해할 수 없는 것을 보았습니다.
int i = 6;
int j;
int *ptr = &i;
int *ptr1 = &j
j = i++;
//now j == 6 and i == 7. Straightforward.
연산자를 등호 왼쪽에 놓으면 어떨까요?
++ptr = ptr1;
와 동등하다
(ptr = ptr + 1) = ptr1;
반면에.
ptr++ = ptr1;
와 동등하다
ptr = ptr + 1 = ptr1;
우편번호에서 컴파일 오류가 발생하여 이해했습니다.할당 연산자의 왼쪽에 상수 "ptr + 1"이 있습니다.그럴 만도대체로.
프리픽스 1은 컴파일되어 C++로 동작합니다.네, 지저분하고 할당되지 않은 기억을 다루시는 건 알지만, 그건 잘 되고 컴파일 됩니다.C에서는 컴파일되지 않고 postfix "lvalue required as left operand of assignment"와 같은 오류가 반환됩니다.이 문제는 "=" 연산자 두 개 또는 "+ptr" 구문을 사용하여 확장하거나 작성 방식에 관계없이 발생합니다.
C가 이러한 할당을 처리하는 방법과 C++가 처리하는 방법의 차이점은 무엇입니까?
와 C C++의 결과입니다.x++
rvalue이기 할 수 없습니다.rvalue는 Rvalue에 되지 않습니다.
식식사는,++x
x += 1
(C 「C」 「6.5.3.1/p2, C」 「C」 「WG14 N1570」).에서는 C++입니다.++x
x += 1
x
아니다bool
(C++ standard 5 . 3 . 2 [ expr . pre . incr ] / p1 " C++ standard crities " WG21 N3936 " ( ( ( 。
C에서 할당식의 결과는 r값(C 표준 §6.5.16/p3)이다.
할당 연산자는 왼쪽 오퍼랜드에 의해 지정된 객체에 값을 기억한다.할당식은 할당 후 왼쪽 피연산자 값을 가지지만 l 값은 아닙니다.
l값이 아니기 때문에 할당할 수 없습니다(C 표준 § 6.5.16/p2 - 이것이 제약사항임을 주의).
할당 연산자는 수정 가능한 l값을 왼쪽 피연산자로 가져야 한다.
C++에서는 할당식의 결과는 l값(C++ 표준 § 5.17 [expr . ass ] / p1)입니다.
할당 연산자(=)와 복합 할당 연산자는 모두 오른쪽에서 왼쪽으로 그룹화합니다.모두 왼쪽 피연산자로 수정 가능한 l값이 필요하며 왼쪽 피연산자를 참조하는 l값을 반환합니다.
★★★★★★★★★★★★★★★★★.++ptr = ptr1;
C에서는 이지만 C.
C, C++11 이전++ptr = ptr1;
되지 않은 동작이 은, 「미정의의 동작」을 변경하기 .ptr
두 개의 인접한 시퀀스 포인트 사이에 두 번.
에서는 C++11의 ,++ptr = ptr1
잘 정의됩니다. 더 요.
(ptr += 1) = ptr1;
C++11 이후 C++ 규격은 다음과 같은 기능을 제공합니다(「5.17 [expr.ass]/p1)
모든 경우, 할당은 좌우 피연산자의 값 계산 후 및 할당식의 값 계산 전에 시퀀싱된다.부정하게 시퀀싱된 함수 호출에 관해 복합 할당의 동작은 단일 평가입니다.
이 되었습니다.=
의 값 계산 후에 배열됩니다.ptr += 1
★★★★★★★★★★★★★★★★★」ptr1
에 의해 +=
is is is is 、 is 、 is 、 is 、 is 、 ationation is isationation 。ptr += 1
에 한 값 +=
반드시 그 할당 전에 시퀀스가 지정됩니다.따라서 이 순서는 명확하게 정의되어 있으며 정의되지 않은 동작은 없습니다.
C에서는 사전 및 사후 증분의 결과가 rvalues이며, rvalues에 할당할 수 없습니다.lvalue가 필요합니다(또한 다음 참조). C 및 C++)의 lvalue와 rvalue에 대해서초안 C11 표준 섹션으로 이동하면 알 수 있습니다.6.5.2.4
포스트픽스 증가 및 감소 연산자는 다음과 같습니다(광산이 앞으로 진행될 것임을 강조합니다).
postfix ++ 연산자의 결과는 피연산자의 값입니다. [...] 제약 조건, 유형 및 변환과 포인터에 대한 작업의 영향에 대한 자세한 내용은 추가 연산자 및 복합 할당에 대한 설명을 참조하십시오. [...]
따라서 post-increment의 결과는 rvalue의 동의어 값이며 섹션으로 이동하여 확인할 수 있습니다.6.5.16
상기 단락에서 제약조건과 결과를 보다 잘 이해하기 위해 지적한 할당 연산자는 다음과 같습니다.
[...] 할당식은 할당 후 왼쪽 피연산자 값을 가지지만 l값은 아닙니다.[...]
이는 사후 분석 결과가 l값이 아님을 더욱 확인시켜준다.
할 수 .6.5.3.1
다음과 같은 프레픽스 증가 연산자 및 감소 연산자:
[...제한조건, 유형, 부작용 및 변환과 포인터에 대한 연산의 영향에 대한 내용은 가법 연산자 및 복합 할당에 대한 설명을 참조하십시오.
, 을 있습니다.6.5.16
증가 후와 마찬가지로 C의 증가 전 결과도 l값이 아닙니다.
C++ 포스트 인크리먼트도 r 값입니다.구체적으로는 pr 값입니다.섹션으로 이동하여 확인할 수 있습니다.5.2.6
증가 및 감소:
[...] 결과는 prvalue입니다.결과 유형은 오퍼랜드 유형의 cv-qualified 버전입니다.[...]
프리 인크리먼트 C와 C++는 다르다.C에서는 결과가 r 값인 반면 C++에서는 결과가 l 값인 이유를 설명합니다.++ptr = ptr1;
C++에서는 동작하지만 C에서는 동작하지 않습니다.
, 는 섹션 C++의 경우, 섹션 C++에 기재되어 .5.3.2
증가 및 감소:
[...] 결과는 업데이트된 피연산자이며 피연산자가 비트 필드일 경우 비트 필드입니다.[...]
다음 사항을 이해하려면:
++ptr = ptr1;
C++에 제대로 정의되어 있는지 아닌지는 C++11 이전과 C++11 이전 두 가지 접근법이 필요합니다.
C++11 이전 버전에서는 이 식이 동일한 시퀀스 포인트 내에서 개체를 여러 번 수정하기 때문에 정의되지 않은 동작을 호출합니다.이것을 확인하려면 , 「C++11 초안」의 항을 참조해 주세요.5
다음을 나타내는 표현:
특별한 언급이 없는 한, 개별 연산자의 피연산자 평가 순서와 개별 표현의 하위 표현, 부작용이 발생하는 순서는 명시되어 있지 않다.57) 스칼라 객체는 앞의 시퀀스 포인트와 다음 시퀀스 포인트 사이에서 표현의 평가에 의해 한 번에 저장된 값을 수정해야 한다.또한 이전 값은 저장할 값을 결정하기 위해서만 접근해야 한다.이 항의 요건은 완전 표현의 하위 표현의 각 허용 순서에 대해 충족되어야 한다. 그렇지 않으면 동작이 정의되지 않는다.[예:
i = v[i ++]; / / the behavior is undefined i = 7 , i++ , i ++; / / i becomes 9 i = ++ i + 1; / / the behavior is undefined i = i + 1; / / the value of i is incremented
: 엔드 예시]
.ptr
하게 되는데,두, 이 식.이것은 2개의 수정이며, 이 경우 시퀀스 포인트는 식 끝에 발생합니다.;
.
C+11 의 경우는, 「결함 리포트 637: Sequencing rules and example disconsign」(시퀀싱 규칙과 예제의 불일치)에 액세스 해, 다음의 결과를 가져온 결함 리포트를 참조해 주세요.
i = ++i + 1;
C++11 이전에는 정의되지 않은 동작이었지만, C++11에서는 올바르게 정의되지 않은 동작이 되었습니다.이 리포트의 설명은 제가 지금까지 본 것 중 하나이며, 여러 번 읽은 것은 계몽적이고, 새로운 관점에서 많은 개념을 이해하는데 도움이 되었습니다.
이 표현이 올바르게 정의되는 동작이 되는 논리는 다음과 같습니다.
할당 부작용은 LHS와 RHS의 값을 모두 계산한 후 배열해야 한다(5.17 [expr.ass] 단락 1).
LHS(i)는 l값이기 때문에 값 계산에는 i의 주소 계산이 포함됩니다.
RHS(+i + 1) 값을 계산하려면 먼저 lvalue 식 ++i 값을 계산한 다음 결과에 대해 lvalue-to-rvalue 변환을 수행해야 합니다.이렇게 하면 가산 연산을 계산하기 전에 증분 부작용이 배열되고, 이는 할당 부작용 전에 배열됩니다.즉, 이 식에 대해 명확하게 정의된 순서와 최종 값을 얻을 수 있습니다.
논리는 다음과 같습니다.
++ptr = ptr1;
LHS와 RHS의 값 계산은 할당 부작용 전에 시퀀싱된다.
RHS는 l값이기 때문에 그 값 계산에는 ptr1의 주소 계산이 포함됩니다.
LHS(++ptr) 값을 계산하려면 먼저 lvalue 식 ++ptr 값을 계산한 다음 결과에 대해 lvalue-to-rvalue 변환을 수행해야 합니다.이렇게 하면 할당 부작용 전에 증가 부작용이 시퀀싱됩니다.즉, 이 식에 대해 명확하게 정의된 순서와 최종 값을 얻을 수 있습니다.
메모
OP는 다음과 같이 말했습니다.
네, 지저분하고 할당되지 않은 기억을 다루시는 건 알지만, 그건 잘 되고 컴파일 됩니다.
비배열 객체에 대한 포인터는 가법 연산자에 대해 크기가 1인 배열로 간주됩니다. C++ 표준 초안을 인용합니다만, C11의 텍스트는 거의 동일합니다.5.7
가법 연산자:
이러한 연산자의 목적상 비배열 객체에 대한 포인터는 객체 유형을 요소 유형으로 하는 길이 1 배열의 첫 번째 요소에 대한 포인터와 동일하게 동작합니다.
또, 포인터를 참조 해제하지 않는 한, 어레이의 끝을 가리키는 포인트는 유효합니다.
[...] 포인터 오퍼랜드와 결과 모두 동일한 배열 객체의 요소를 가리키거나 배열 객체의 마지막 요소를 가리키는 경우 평가에서 오버플로가 발생하지 않습니다.그렇지 않으면 동작은 정의되지 않습니다.
따라서:
++ptr ;
는 아직 유효한 포인터입니다.
언급URL : https://stackoverflow.com/questions/25654339/the-difference-between-c-and-c-regarding-the-operator
'programing' 카테고리의 다른 글
Java 문자열 바이트 수 (0) | 2022.07.26 |
---|---|
vue-module 네비게이션 바를 유지하는 방법 (0) | 2022.07.26 |
커밋을 사용한 액션에서 VueX 업데이트 상태 (0) | 2022.07.26 |
Vue.js 단일 파일 컴포넌트 로드 (0) | 2022.07.26 |
warning: Error disabling address space randomization: Operation not permitted (0) | 2022.07.26 |