IT

c = ++ (a + b)가 발생 오류를 발생시키는 이유는 무엇입니까?

lottoking 2020. 7. 29. 07:34
반응형

c = ++ (a + b)가 발생 오류를 발생시키는 이유는 무엇입니까?


조사 한 후 증가 연산자는 피연산자에 수정 가능한 데이터가 있음을 읽었습니다. https://en.wikipedia.org/wiki/Increment_and_decrement_operators .

나는 (a+b)임시 정수 이기 때문에 오류가 발생 하고 수정 할 수 있다고 생각합니다.

이 이해가 맞습니까? 처음으로 문제를 조사하려고 때문에 찾아 볼 것이 좋습니다.


그것은 단지 규칙 일 뿐이며, 아마도 (1) ​​C 컴파일러를보다 쉽게 ​​작성할 수있게하고, (2) 아무도 C 표준위원회가이를 거부 설득하지 않았습니다.

으로는 비공식적 과 같은 대입 식의 왼쪽에 나타날 수있는 ++foo경우 에만 쓸 foo있습니다 foo = bar. 글을 쓸 a + b = bar수 없습니다 글도 쓸 수 없습니다 ++(a + b).

작동 할 수 a + b있는 임시를 생성 할 수없는 실제적인 이유 는 수준 ++, 그 결과는 표현의 가치입니다 ++(a + b).


섹션 6.5.3.1의 C11 표준 상태

접두사 증가 또는 감소 연산자의 피연산자는 원자, 정규화 또는 정규화되지 않은 실수 또는 포인터 유형을 가져와 수정 가능한 lvalue를받습니다.

"수정 가능한 lvalue"는 섹션 6.3.2.1 하위 섹션 1에 설명되어 있습니다.

lvalue는 특별한 객체를 지정하는 것입니다. lvalue가 평가 될 때 오브젝트를 지정하지 않습니다. 유형 지정에 특정 유형이 사용되는 lvalue가 지정됩니다. 수정 가능한 lvalue는 배열 유형이없고 불완전한 유형이 const 한정 유형이 구조 또는 공용체 인 경우 한정 유형 멤버를 포함하지 않는 lvalue입니다 (재귀 적으로 모든 멤버 포함) const 한정 유형의 모든 멤버가 포함되어 공용 또는 체의 요소) .

따라서 (a+b)수정 가능한 lvalue가 아니 접두사 증가 연산자에 적합하지 않습니다.


당신이 올바른지. ++원래 변수에 새로운 값을 할당합니다. 따라서 ++a값을 가져 오기 a더한 1다음 다시 할당합니다 a. 앞에서 언급했듯이 (a + b)는 임시 값이며 메모리 주소가 할당 된 변수가 아니 할당을 수행 할 수 없습니다.


나는 당신이 대부분 자신의 질문에 대답한다고 생각합니다. C.Gibbons에서 언급했듯이 귀하의 문구를 약간 변경하고 "임시 변수"를 "rvalue"로 바꿀 수 있습니다.

C의 메모리 모델에 대해 배우면 변수, 인수, 임시 변수 등의 용어가 더 명확하게 해 (이것은 좋은 개요처럼보기 : https://www.geeksforgeeks.org/memory-layout-of-c-program/ ) .

"rvalue"라는 용어는 막 시작했을 때 불투명 해 보일 수 있으므로 다음 내용이 직관을 개발하는 데 도움이됩니다.

Lvalue / rvalue는 등호 (할당 연산자)의 다른 부분에 대해 말하고 있습니다. lvalue = 왼쪽 ( "1"이 아닌 소문자 L) rvalue = 오른쪽

C가 메모리 (및 다소)를 사용하는 방법에 대해 조금 배우면 구별이 왜 중요한지 알 수 있습니다. 에서 폭 넓은 넓은 문장 , 컴파일러는 표현합니다 (를 rvalue)의 결과를 계산하는 기계 언어의 목록을 만든 다음 박았 그 결과 어딘가합니다 (좌변)을. 다음 코드 조각을 처리하는 컴파일러를 상상해.

x = y * 3

어셈블리 의사 코드에서는 다음 장난감 예제와 같이 보일 수 있습니다 .

load register A with the value at memory address y
load register B with a value of 3
multiply register A and B, saving the result in A
write register A to memory address x

++ 연산자 (및 해당 연산자)는 수정 비용 "어딘가"가 필요합니다. 기본적으로 lvalue로 작동 할 수있는 모든 것이 있습니다.

C 메모리 모델을 이해하면 인수가 함수에 전달되는 방법과 malloc () 함수와 같은 동적 메모리 할당 작업에 대해 더 잘 이해할 수 있기 때문에 도움이 될 것입니다. 어느 시점에서 간단한 어셈블리 프로그래밍을 공부하는지 컴파일러가하는 일을 더 잘 사용할 수 있습니다. 또한 gcc 를 사용하는 경우 -S "컴파일 단계가 중지하고 어셈블하지 않고" 흥미로울 수 있습니다 ( 작은 코드 조각으로 시도해 보는 것이 좋습니다 ).

++ 명령 은 1969 년 이래로 C의 전임자 B에서 시작하는 다음과 같습니다.

(켄 톰슨 (Ken Thompson))의 관찰에 따르면 ++ x의 번역은 x = x + 1의 번역보다 작습니다. "

위키 백과를 참조하면 C 언어의 역사에 대한 Dennis Ritchie ( "K & R C"의 "R")가 편의를 위해 여기에 링크 한 흥미로운 글을 쓸 수 있습니다. http://www.bell-labs.com/ "++"를 검색 할 수있는 usr / dmr / www / chist.html


그 이유는 표준에 피연산자가 필요하기 때문입니다. (a+b)많은 연산자를 적용 할 수 없습니다.

이제, 하나는 말할 수있다 "정말로 이유지만, 실제로는 더 * 진짜 *의보다 다른 이유가 없다는 것을 확인" 하지만 불행하게도 운전자가 사실로 작동하는 방법의 특정 문구 않는 경우가 해당이 필요가.

++ E 서식은 (E + = 1)과 가변합니다.

좌변 아닌가 E += 1경우 에는 쓸 수 없습니다 E. "E를 하나씩 증가" 는 말과 함께 할 수 있었기 때문에 부끄러운 일입니다. 이 경우, 원칙적으로 컴파일러를 약간 더 복잡하게 만드는 것이, 비 가치에 연산자를 적용하는 것이 완벽하게 가능합니다.

이제, 그 정의는 사소하게 변경 될 수 있습니다 (저는 원래 C가 아니라 B의 가보라고 생각합니다). 그렇게하면 언어가 더 이상 이전 버전과 호환되지 않는 언어로 변경 될 것입니다. 가능한 이점은 다소 작지만 가능한 의미는 크거나 발생하지 않을 가능성이 있습니다.

C는 C ++을 고려한다면 (질문에 C 태그가 선택하면 연산자 오버로드에 대한 논의가 있었다면) 이야기는 훨씬 복잡해집니다. C에서는 이것이 사실 일 수 있습니다 상상하기 어렵지만 C ++의 결과 (a+b)는 전혀 증가하지 않는 결과가 될 수 있거나 증가하는 것은 1을 추가하는 것이 아니라 매우 중요한 부작용을 수 있습니다. 컴파일러는 이에 필요하고 문제가있을 경우에만 진단 할 수 있습니다. lvalue에서는 여전히 확인하기가 쉽지 않습니다. 괄호 안의 어떤 종류의 우연한 표현에는 좋지 않은 것을 던질 수 있습니다.
이것이 실제로 실패한 이유 는 아닙니다 그러나 구현 한 한 사람들이 극소수의 사람들에게 거의 혜택을주지 않는 기능을 추가하는 것이 정확히 황홀하지 않습니다.


(a + b)는 rvalue로 평가 증분 할 수 없습니다.


++는 원래 변수에 값을 주려고 시도하고 (a + b)는 임시 값 출시 작업을 수행 할 수 없습니다. 그리고 기본적으로 프로그래밍을 쉽게하기 위해 C 프로그래밍 규칙의 규칙입니다. 그게 다야.


++ (a + b) 이렇게하면 다음과 사용할 수 있습니다.

int a, b;
a = 10;
b = 20;
/* NOTE :
 //step 1: expression need to solve first to perform ++ operation over operand
   ++ ( exp );
// in your case 
   ++ ( 10 + 20 );
// step 2: result of that inc by one 
   ++ ( 30 );
// here, you're applying ++ operator over constant value and it's invalid use of ++ operator 
*/
++(a+b);

참고 URL : https://stackoverflow.com/questions/50951261/why-does-c-ab-give-compilation-error

반응형