왜 +++++B가 작동하지 않는가?
int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
이 코드는 다음과 같은 오류를 제공한다.
오류: 증분 피연산자에 필요한 l값
하지만 만약 내가 모든 곳에 공간을 둔다면a++ +
그리고++b
그럼 잘 될 거야
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
첫 번째 예에서 오류가 의미하는 것은?
printf("%d",a+++++b);
로 해석되다(a++)++ + b
막시말 뭉크 규칙에! 따라
++
는 (postfix) 가(postfix)에 평가되지 않는다.lvalue
하지만 피연산자가 될 필요가 있다.lvalue
.
! 6.4/4는 다음 사전 처리 토큰이 사전 처리 토큰을 구성할 수 있는 가장 긴 문자 시퀀스라고 말한다."
컴파일러는 단계별로 작성된다.첫 번째 단계는 렉서라고 불리며 캐릭터를 상징적인 구조로 바꾼다.그래서 "+"는 일종의 "+"와 같은 것이 된다.enum SYMBOL_PLUSPLUS
파서 수 나중에 파서 단계는 이것을 추상 구문 트리로 바꾸지만 기호를 변경할 수는 없다.공백(따옴표에 없는 경우 기호가 끝나는 것)을 삽입하여 렉서에게 영향을 줄 수 있다.
일반 렉서들은 (일부 예외를 제외하고는) 욕심이 많아서 당신의 코드는 다음과 같이 해석되고 있다.
a++ ++ +b
파서 입력은 기호의 스트림이므로, 당신의 코드는 다음과 같다.
[ SYMBOL_NAME(name = "a"),
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS_PLUS,
SYMBOL_PLUS,
SYMBOL_NAME(name = "b")
]
파서가 구문론적으로 틀렸다고 생각하는 것. (주석을 바탕으로 한 EDIT:r-값에 ++를 적용할 수 없으므로 의미론적으로 부정확하며, 이 경우 a++)
a+++b
이다
a++ +b
괜찮다.너의 다른 예들도 그렇다.
이 정확한 예는 C99 표준 초안(C11의 동일한 세부사항) 6.4 어휘소 요소 제4항에서 다루며, 이 초안은 다음과 같다.
입력 스트림을 지정된 문자까지 사전 처리 토큰으로 구문 분석했다면 다음 사전 처리 토큰은 사전 처리 토큰을 구성할 수 있는 가장 긴 문자 시퀀스다. [...]
모호함을 피하기 위해 어휘 분석에 사용되는 최대 뭉치 규칙이라고도 하며 유효한 토큰을 형성하기 위해 가능한 많은 요소를 취함으로써 작동한다.
단락은 또한 두 가지 예를 가지고 있다. 두 번째 예는 당신이 질문하는 것과 정확히 일치하며 다음과 같다.
예 2 프로그램 조각 x+++++++++++++++++로 구문 분석하는데, 구문 분석 x+++++++ y가 정확한 식을 산출할 수 있더라도 증분 연산자의 제약조건을 위반한다.
이는 우리에게 다음과 같은 것을 말해준다.
a+++++b
다음과 같이 구문 분석한다.
a ++ ++ + b
첫 번째 포스트 증분의 결과가 r값이고 포스트 증분의 결과가 l값을 요구하기 때문에 포스트 증분의 제약조건을 위반한다.이 내용은 섹션에 설명되어 있다.6.5.2.4
(내 것 강조)라고 말하는 사후 처리 증가 및 감소 연산자:
사후 처리 증감 운영자의 피연산자는 적격 또는 부적격의 실제 또는 포인터 유형을 가져야 하며 수정 가능한 l값이어야 한다.
그리고
사후 수정 ++ 연산자의 결과는 피연산자의 값이다.
C++고차스라는 책에는 이 사건도 수록되어 있다.Gotcha #17
Maximal Munch 문제 그것은 C++에서도 같은 문제이고 몇 가지 예를 들기도 한다.다음과 같은 문자 집합을 다룰 때는 다음과 같이 설명한다.
->*
어휘 분석기는 다음 세 가지 중 하나를 수행할 수 있다.
- 다음 세 개의 토큰으로 처리하십시오.
-
>
그리고*
- 두 개의 토큰으로 처리:
->
그리고*
- 하나의 토큰으로 처리:
->*
최대 우묵한 규칙으로 인해 이러한 애매한 점들을 피할 수 있다.저자는 (C++ 컨텍스트에서) 다음과 같이 지적한다.
그것이 야기하는 것보다 더 많은 문제를 해결하지만, 두 가지 일반적인 상황에서, 그것은 성가신 일이다.
첫 번째 예는 템플릿 인수가 템플릿(C++11에서 해결됨)인 템플릿이다. 예를 들어,
list<vector<string>> lovos; // error!
^^
이는 닫히는 각 브래킷을 시프트 연산자로 해석하여 다음과 같이 모호하게 하기 위해 공간이 필요하다.
list< vector<string> > lovos;
^
두 번째 경우는 다음과 같은 포인터의 기본 인수를 포함한다.
void process( const char *= 0 ); // error!
^^
라고 해석될 것이다.*=
할당 연산자, 이 경우 해결책은 선언문에 매개변수의 이름을 지정하는 것이다.
(a++)++ +b
a++는 이전 값인 r값을 반환한다.이건 증분할 수 없어.
렉서는 토큰을 만들기 위해 일반적으로 "maximum munch" 알고리즘을 사용한다.즉, 문자를 읽을 때 이미 가지고 있는 것과 같은 토큰의 일부가 될 수 없는 것을 만날 때까지(예를 들어 숫자를 읽고 있으면 숫자가 된다), 문자를 계속 읽게 된다는 뜻이다.A
그게 숫자의 일부가 될 수 없다는 걸 알고 있어그래서 그것은 멈추고 그 곳을 떠난다.A
다음 토큰의 시작 부분으로 사용할 입력 버퍼).그런 다음 그 토큰을 파서에게 돌려준다.
이 경우, 그것은 의미하는 것이다.+++++
로 선택되다.a ++ ++ + b
. 첫 번째 증가는 r값을 산출하기 때문에 두 번째 증가는 적용할 수 없고, 컴파일러는 오류를 준다.
단지 FWIW, C++에서는 과부하할 수 있다.operator++
lvalue를 산출할 수 있도록 하는 겁니다.예를 들면 다음과 같다.
struct bad_code {
bad_code &operator++(int) {
return *this;
}
int operator+(bad_code const &other) {
return 1;
}
};
int main() {
bad_code a, b;
int c = a+++++b;
return 0;
}
내가 가지고 있는 C++ 컴파일러(VC++, g+++, 코모)로 컴파일과 런(아무것도 하지 않지만)을 한다.
컴파일러는 이렇게 보는 것 같아.
c = ((a++)+++b
++
수정될 수 있는 값을 피연산자로 가져야 한다.a는 수정할 수 있는 값이다. a++
그러나 'rvalue'는 수정될 수 없다.
내가 GCC C에서 보는 오류는 같지만, 다른 말로 표현된다.lvalue required as increment operand
.
컴파일러는 필사적으로 구문 분석하려고 한다.a+++++b
, 그리고 그것을 로 해석하다.(a++)++ +b
.자,후증가(후증가)의 결과.a++
)은 l값(lvalue), 즉, 다시 후증가할 수 없다.
생산품질 프로그램에서는 절대로 그런 코드를 쓰지 마십시오.너의 코드를 해석해야 할 불쌍한 사람이 너를 쫓아오는 것을 생각해봐.
왜냐하면 그것은 정의되지 않은 행동을 일으키기 때문이다.
어느 쪽이야?
c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)
그래, 자네도 컴파일러도 그걸 몰라
편집:
진짜 이유는 다른 사람들이 말한 것이다.
된다.(a++)++ + b
.
그러나 사후 증분에는 lvalue(이름이 있는 변수)가 필요하지만 (a++)는 증분할 수 없는 rvalue를 반환하여 오류 메시지를 받게 된다.
다른 사람들이 이것을 지적하도록 해라.
이 사전 결정 순서를 따르십시오.
1.++(사전 증가)
2.+ - (추출 또는 뺄셈)
3.x"+ "y" 순서 모두 추가
int a = 5,b = 2; printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment return 0; //it is 5+3=8
참조URL: https://stackoverflow.com/questions/5341202/why-doesnt-ab-work
'programing' 카테고리의 다른 글
vuex 페이로드가 정의되지 않음 (0) | 2022.05.10 |
---|---|
Vue Js 단일 파일 템플릿에서 혼합물을 사용하는 방법? (0) | 2022.05.09 |
C에서 사전을 구현하는 빠른 방법 (0) | 2022.05.09 |
Vuejs 구성 요소 템플릿에는 루트 1개 요소만 필요한가? (0) | 2022.05.09 |
vue.js 다이내믹 구성 요소의 keep-alive와 함께 cytoscape.js를 사용하는 방법? (0) | 2022.05.09 |