컴파일러는 여기서 무엇을합니까 : int a = b * (c * d * + e)?
이 질문에 이미 답변이 있습니다.
- 단항 더하기 연산자는 무엇을합니까? 14 답변
프로그램에 이상한 버그가 생겼고 몇 시간 동안 디버깅 한 후 다음과 같은 매우 멍청한 줄을 발견했습니다.
int a = b * (c * d * + e)
당신은 그것을 표시되지 않는 경우 : 사이 d
와 e
내가 쓴 * +
단지는 어디 +
예정되었다.
왜 이것이 컴파일되고 실제로 무엇을 의미합니까?
는 +
단항 플러스 연산자로 해석됩니다. 단순히 피연산자 의 승격 된 값을 반환합니다 .
단항 +
은 승격 된 값을 반환합니다.
단항 -
은 부정을 반환합니다.
int a = 5;
int b = 6;
unsigned int c = 3;
std::cout << (a * +b); // = 30
std::cout << (a * -b); // = -30
std::cout << (1 * -c); // = 4294967293 (2^32 - 3)
+
는 정수 또는 열거 유형에 대한 정수 승격을 수행하고 승격 된 피연산자의 유형을 갖는 단항 더하기로 해석 되기 때문에 컴파일됩니다 .
e
정수 또는 범위가 지정되지 않은 열거 유형 이라고 가정하면 일반적인 산술 변환 을 피연산자에 *
적용하여 정수 유형에 대한 정수 프로모션으로 끝나기 때문에 어쨌든 정수 프로모션이 적용 됩니다 .
초안 C ++ 표준 5.3.1
[expr.unary.op]에서 :
단항 + 연산자의 피연산자는 산술, 범위가 지정되지 않은 열거 또는 포인터 유형을 가져야하며 결과는 인수의 값입니다. 적분 승격은 적분 또는 열거 피연산자에서 수행됩니다. 결과 유형은 승격 된 피연산자의 유형입니다.
통합 프로모션은 4.5
[conv.prom] 섹션에서 다루고 변수 e
가 int 이외의 유형 bool, char16_t, char32_t, or wchar_t
이고 변환 순위가 int 보다 작은 경우 다음 단락으로 처리됩니다 1
.
정수 변환 순위 (4.13)가 int의 순위보다 작은 bool, char16_t, char32_t 또는 wchar_t 이외의 정수 유형의 prvalue는 int가 소스 유형의 모든 값을 나타낼 수있는 경우 int 유형의 prvalue로 변환 될 수 있습니다. ; 그렇지 않으면 소스 prvalue를 unsigned int 유형의 prvalue로 변환 할 수 있습니다.
완전한 케이스 세트에 대해서는 cppreference를 볼 수 있습니다 .
단항 더하기는 모호성을 해결하기 위해 일부 경우에 유용 할 수도 있습니다. 흥미로운 경우는 +를 사용하여 람다에 대한 함수 포인터 및 std :: function에 대한 모호한 오버로드 해결 에서 찾을 수 있습니다 .
단항 -
및 음수 값을 참조하는 해당 답변의 경우 다음 예제에서 볼 수 있듯이 잘못된 것입니다.
#include <iostream>
int main()
{
unsigned x1 = 1 ;
std::cout << -x1 << std::endl ;
}
결과 :
4294967295
wandbox에서 gcc를 사용하여 실시간 으로 확인하세요 .
국제 표준에 대한 이론적 근거 — 프로그래밍 언어 —C :
C89위원회는 단항 마이너스와의 대칭을 위해 여러 구현에서 단항 플러스를 채택했습니다.
캐스팅만으로는 원하는 프로모션 / 전환을 달성하기에 충분하지 않은 좋은 사례를 찾을 수 없습니다. 위에서 인용 한 람다 예제는 단항 더하기를 사용하여 람다식이 함수 포인터로 변환되도록 강제합니다.
foo( +[](){} ); // not ambiguous (calls the function pointer overload)
명시 적 캐스트를 사용하여 수행 할 수 있습니다.
foo( static_cast<void (*)()>( [](){} ) );
의도가 명시 적이기 때문에이 코드가 더 낫다고 주장 할 수 있습니다.
가치 지적이 주석 C ++ 참조 설명서 ( ARM ) 는 다음과 같은 해설이 있습니다 :
단항 플러스는 역사적인 사고이며 일반적으로 쓸모가 없습니다.
그들이 설명했듯이 (+)와 (-)는 단항 연산자로 사용되었습니다.
단항 연산자 는 표현식에서 하나의 피연산자에만 작동합니다.
int value = 6;
int negativeInt = -5;
int positiveInt = +5;
cout << (value * negativeInt); // 6 * -5 = -30
cout << (value * positiveInt); // 6 * +5 = 30
cout << (value * - negativeInt); // 6 * -(-5) = 30
cout << (value * + negativeInt); // 6 * +(-5) = -30
cout << (value * - positiveInt); // 6 * -(+5) = -30
cout << (value * + positiveInt); // 6 * +(+5) = 30
그래서 당신의 코드에서 :
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int a = b * (c * d * + e)
//result: 2 * (3 * 4 * (+5) ) = 120
왜 컴파일됩니까? +
더하기 연산자가 아니라 단항 더하기 연산자로 구문 분석 되기 때문에 컴파일됩니다 . 컴파일러는 구문 오류를 생성하지 않고 가능한 한 많이 구문 분석을 시도합니다. 그래서 이거:
d * + e
다음과 같이 구문 분석됩니다.
d
(피연산자)*
(곱하기 연산자)+
(단항 더하기 연산자)e
(피연산자)
반면, 이것은 :
d*++e;
다음과 같이 구문 분석됩니다.
d
(피연산자)*
(곱하기 연산자)++
(사전 증분 연산자)e
(피연산자)
또한 이것은 :
d*+++e;
다음과 같이 구문 분석됩니다.
d
(피연산자)*
(곱하기 연산자)++
(사전 증분 연산자)+
(단항 더하기 연산자)e
(피연산자)
구문 오류가 아니라 "LValue requrired"컴파일러 오류가 발생합니다.
To put a further twist on the correct answers already given here, if you compile with the -s flag, the C compiler will output an assembly file in which actual the instructions generated can be examined. With the following C code:
int b=1, c=2, d=3, e=4;
int a = b * (c * d * + e);
The generated assembly (using gcc, compiling for amd64) begins with:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
movl $3, -12(%ebp)
movl $4, -8(%ebp)
so we can identify individual memory positions -20(%ebp) as variable b, down to -8(%ebp) as variable e. -4(%epp) is variable a. Now, the calculation is rendered as:
movl -16(%ebp), %eax
imull -12(%ebp), %eax
imull -8(%ebp), %eax
imull -20(%ebp), %eax
movl %eax, -4(%ebp)
So, as has been commented by other people replying, the compiler simply treats "+e" as the unary positive operation. The first movl instruction places the contents of variable e into the EAX accumulator register, which is then promptly multiplied by the contents of variable d or -12(%ebp), etc.
This is just basic math. For example:
5 * -4 = -20
5 * +4 = 5 * 4 = 20
-5 * -4 = 20
Negative * Negative = Positive
Positive * Negative = Negative
Positive * Positive = Positive
This is the easiest explanation there is.
The minus(-) and plus(+) just tell if the number is positive or negative.
The + operator between d and e will be treated as an unary + operator which will determine only sign of e. So the compiler will see this statement as follow:
int a = b*(c*d*e) ;
참고URL : https://stackoverflow.com/questions/30361112/what-does-the-compiler-do-here-int-a-b-c-d-e
'code' 카테고리의 다른 글
@synthesized getter를 재정의하는 방법은 무엇입니까? (0) | 2020.10.23 |
---|---|
ORA-28040 : 일치하는 인증 프로토콜 예외 없음 (0) | 2020.10.23 |
컨테이너 이름에서 도커 컨테이너 ID 가져 오기 (0) | 2020.10.23 |
PHP에서 동적 클래스 메서드 호출 (0) | 2020.10.23 |
명시 적 형변환을 사용하여 파생 클래스 참조에 기본 클래스 개체를 할당 할 수 있습니까? (0) | 2020.10.23 |