2012-05-25 4 views
1
usigned int x=1; 
signed int y = -1; 
double z = y * x * 0.25; 

Microsoft Visual Studio 10 C++ 컴파일러를 사용하고 있습니다. 왜 z에는 -0.25 값이 없습니까? 해시에서 보았 듯이 부호있는 int 곱셈 (imul)을 만들고, edx의 결과를 스택에 배치하고, 부호없는 int 일 때 0으로 확장합니다. 그런 다음 FP 명령을 사용하여이를 곱합니다.Microsoft C++ 컴파일러에 버그가 있습니까?

............. 
imul  edx,dword ptr [ecx] 
mov   dword ptr [ebp-98h],edx 
mov   dword ptr [ebp-94h],0 
fild  dword ptr [ebp-98h] 
fmul  qword ptr [[email protected] (1402FB8h)] 
fstp  qword ptr [z] 

왜 서명 된 * 부호없는 결과가 부호없는 것으로 해석되는 이유는 무엇입니까?

+0

어디에서 영 (zero) 확장자가 보입니까? '[ebp-94h]'는 곱셈의 결과와 관련이 없으며'fild'는'qword '가 아닌'dword'를 취합니다. – Dani

+0

서로 다른 정수 타입이 바이너리 연산에 참여하는 매우 구체적인 통합 승격 규칙이 있습니다. 내 추측에 따르면, 어딘가에 올바른 행동이 무엇인지 정정 될 것이지만 솔직히 그것은 엉망입니다. –

+0

그래, 맞아, 컴파일러를 비난 해. –

답변

7

표현식 y * x * 0.25은 C 및 C++ 모두에서 (y * x) * 0.25과 연관됩니다.

unsigned intsigned int 승산 두 피연산자 unsigned int 변환되고 y * x 결과는 모두 C에 UINT_MAX - 1 수 있도록 결과 인해 C 및 C 모두의 산술 표현식 정수 변환 규칙 ++로도 unsigned int 인 및 C++.

귀하의 예제는 C 또는 C++로 예제를 컴파일하던간에 컴파일러 버그를 나타내지 않습니다.

+0

컴파일러 버그가 아니라면 나에게 더욱 나쁜 것처럼 보입니다. C++ 사양 결함 또는 "사양 버그" 수학적으로 말해서 음수와 양수를 곱하면 그 결과는 분명히 부정적입니다. 그렇다면 부자연스런 규칙을 가진 엔지니어를 왜 혼동하게합니까? – asu

5

이것은 실제로 사양에 따른 것입니다. C++ 11, 5.9 : 비슷한 방법으로 산술 또는 열거 형의 원인 변환 및 수율 결과 유형의 피연산자를 기대

많은 이항 연산자. 목적은 일반적인 유형을 산출하는 것이며 결과는 또한 입니다.

[...]

그렇지 적분 프로모션 (4.5) 모두 피연산자에 대해 수행되어야한다 : 다음과 같이 정의 된 패턴은 통상의 산술 전환 불린다. 그러면 다음 규칙들은 승진 피연산자에 적용한다 :

[...]

  • 그렇지 부호 정수의 형태를 가진 피연산자는 계급 이상인 순위 가 있는지 다른 피연산자의 타입이 이면 부호있는 정수 타입을 갖는 피연산자는 부호없는 정수 타입을 갖는 피연산자 의 타입으로 변환되어야한다. 여기에서 y * x

두 피연산자는 동일한 부호를 integer conversion rank 지능 서명되고; 그래서 y은 결국 서명되지 않은 것으로 변환됩니다.

+0

이 특별한 경우에는 통합 프로모션이 수행되지 않습니다. – Lundin

+0

@ Lundin : 모든 * 해당 * 필수 프로모션이 완료되었습니다. 이 경우 적용 할 수있는 것이 없습니다. IMHO는 그렇게 나쁜 표현이 아닙니다. – Jon

+0

나는 그 부분을 인용 한 이유에 대해 궁금해했다. 아마도 OP를 혼란스럽게 만들 것이기 ​​때문이다. – Lundin

3

이것은 표준 [EXPR] 절에서 설명

....

그렇지 적분 프로모션 (4.5) 모두 피연산자에 대해 수행되어야한다.그런 다음 승격 된 피연산자에 다음 규칙이 적용됩니다.

- 두 피연산자 모두 동일한 유형 인 경우 더 이상 변환하지 않습니다. 이 필요합니다.

이 - 두 피연산자가 정수 타입을 체결 또는 경우 그렇지 않으면, 모두 부호없는 정수 유형이 덜 정수 변환 순위의 유형 피연산자는 큰 순위와 피연산자 의 형식으로 변환해야한다.

은 - 정수형 서명되지 않은 피연산자가 큰 계급 그렇지 않고, 만일 유형 다른 피연산자, 부호있는 정수 유형 오퍼랜드의 랭크 같음 피연산자의 형식으로 변환한다보다 부호없는 정수 유형.

표현식의 왼쪽에서 오른쪽으로 계산되므로 y * x이 먼저 계산됩니다. 이것은 동일한 랭크의 두 개의 정수형, 한 개의 피연산자와 다른 하나의 부호없는 타입을가집니다. 따라서 표준 추출의 마지막 단락에서 설명한 것처럼 부호가있는 값은 부호없는 값으로 변환됩니다.

관련 문제