programing

a++++b가 왜 안 되지?

randomtip 2022. 8. 29. 21:46
반응형

a++++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)로 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") 
]

파서는 구문적으로 올바르지 않다고 생각합니다.(코멘트에 근거해 편집:r-값에는 ++를 적용할 수 없기 때문에 의미론적으로 올바르지 않습니다.그 결과 a++가 됩니다).

a+++b 

a++ +b

괜찮아요.다른 사례들도 마찬가지입니다.

이 정확한 사례는 초안 C99(C11의 동일한 세부사항) 섹션 6.4 어휘요소 문단 4에서 다루며, 다음과 같이 기술되어 있다.

입력 스트림이 지정된 문자까지 전처리 토큰으로 구문 분석된 경우 다음 전처리 토큰은 전처리 토큰을 구성할 수 있는 가장 긴 문자 시퀀스가 됩니다.[ ... ]

이것은 또한 어휘 분석에서 모호함을 피하기 위해 사용되는 최대 뭉크 규칙으로도 알려져 있으며 유효한 토큰을 형성하기 위해 가능한 많은 요소들을 취함으로써 작용한다.

이 단락에는 두 가지 예제가 있습니다.두 번째 예시는 질문과 완전히 일치하며 다음과 같습니다.

예 2 프로그램 fragment x++++y는 x +++++y로 해석되며, 이는 파싱 x ++++ y가 올바른 식을 산출할 수 있는 경우에도 증분 연산자에 대한 제약을 위반합니다.

즉, 다음과 같습니다.

a+++++b

다음과 같이 해석됩니다.

a ++ ++ + b

이는 첫 번째 포스트 인크리먼트의 결과가 r 값이고 포스트 인크리먼트의 결과가 l 값이 필요하기 때문에 포스트 인크리먼트의 제약을 위반한다.는, 「 」의 항에 기재되어 있습니다.6.5.2.4 포스트픽스 증가감소 연산자는 다음과 같습니다(강조 광산).

포스트픽스 증분 또는 감소 연산자의 피연산자는 적격 또는 부적격 실수 또는 포인터 유형을 가져야 하며 수정 가능한 l값이어야 한다.

그리고.

postfix ++ 연산자의 결과는 피연산자의 값입니다.

C++ Gotchas라는 책도 이 경우를 다루고 있다.Gotcha #17 최대 뭉크 문제 C++에서도 같은 문제이고 또한 몇 가지 예를 제시합니다.다음의 문자 세트를 취급하는 경우는, 다음과 같이 설명하고 있습니다.

->*

어휘 분석기는 다음 세 가지 중 하나를 수행할 수 있습니다.

  • 합니다: 3개의 토큰이 있습니다.-,> ★★★★★★★★★★★★★★★★★」*
  • 하세요: 2개의 토큰으로요.-> ★★★★★★★★★★★★★★★★★」*
  • 하나의 토큰으로 취급합니다.->*

최대 뭉크 법칙은 이러한 모호함을 피할 수 있게 해준다.저자는 (C++ 컨텍스트에서) 다음과 같이 지적합니다.

원인이 되는 것보다 더 많은 문제를 해결하지만 두 가지 일반적인 상황에서는 골칫거리입니다.

첫 번째 예는 템플릿 인수도 템플릿(C++11에서 해결)인 템플릿입니다.다음은 예를 제시하겠습니다.

list<vector<string>> lovos; // error!
                  ^^

그러면 닫힘 각도 대괄호가 시프트 연산자로 해석되므로 다음 사항을 명확히 하기 위해 공백이 필요합니다.

list< vector<string> > lovos;
                    ^

두 번째 예에서는 다음과 같은 포인터의 기본 인수를 사용합니다.

void process( const char *= 0 ); // error!
                         ^^

라고 할 수 있다*= 이 assignment, assignment의 에 이름을 입니다.

(a++)++ +b

a++는 이전 값인 r값을 반환합니다.이 값은 늘릴 수 없습니다.

이 렉서는 토큰을 만들기 위해 일반적으로 "최대 뭉크" 알고리즘이라고 불리는 알고리즘을 사용합니다. 때 있는 과 같은 수 들어 숫자를 를 읽을 수 있는 , 문자를 숫자가 ).A멈추다, , 남았습니다.A입력 버퍼에서 다음 토큰의 선두로 사용합니다).그런 다음 해당 토큰을 파서로 반환합니다.

즉, 「」, 「」, 「」, 「」, 「」를 의미합니다.+++++로 분류되다.a ++ ++ + b첫 번째 post-increment는 r값을 생성하므로 두 번째 post-increment는 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++, Comeau)를 사용하여 컴파일 및 실행합니다.

컴파일러는 이렇게 보는 것 같아요.

c = (a++) + b

++operand로서 변경할 수 있는 값을 가질 필요가 있습니다.a는 변경할 수 있는 값입니다. a++ 'rvalue ' 'rvalue', 'rvalue', 'rvalue'는 'rvalue'는 'rvalue'입니다.

에서 볼 수 있는 로 되어 있습니다: "GCC C"입니다.lvalue required as increment operand.

으로 해석하려고 .a+++++b합니다.(a++)++ +b이제 、 가 . 、 가 . 、 . . ( )a++)는 l값이 아닙니다.즉, 다시 증분할 수 없습니다.

생산품질 프로그램에는 절대 그런 코드를 쓰지 마세요.당신의 코드를 해석해야 하는 불쌍한 사람을 생각해 보세요.

정의되지 않은 동작을 일으키기 때문입니다.

어느 쪽일까요?

c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)

그래, 너도 컴파일러도 몰라

편집:

진짜 이유는 다른 사람들이 말한 것 중 하나입니다.

할 수 있습니다.(a++)++ + b.

그러나 post increment에는 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/5677271/why-doesnt-c-ab-work-in-c

반응형