2009-05-09 4 views
1

잘못된 결과를 출력하는 코드가 있습니다.memcpy가 수행하지 않는 것 같습니다.

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    unsigned char bytes[4]; 
    float flt=0; 

    bytes[0]=0xde; 
    bytes[1]=0xad; 
    bytes[2]=0xbe; 
    bytes[3]=0xef; 

    memcpy(&flt, bytes, 4); 

    printf("bytes 0x%x float %e\n", flt, flt); 
    return 0; 
} 

I가 얻을 출력

바이트 0xC0000000과 플로트 -2.000001e + 00

내가

이 이

바이트 -6.2598534e을 떠을 0xdeadbeef

얻을 것으로 기대하고있다 +18

,210

편집 # 1 지적되었을 때 엔디안 -1.1802469e은 내가 이해할 수없는 것은 29

입니다 + 떠 0xefbeadde 다음

바이트 초래할 것이다 다를 수 있습니다 float에서 unsigned int로 변환하여 0xc0000000이됩니다 (동일한 printf 문에서 부동 소수점이 -2.0000이되면 컴파일러 최적화에 영향을 미칩니다)

다른 컴퓨터에서 이전에 작동했습니다. 아키텍처 변화 일 수 있습니다.

답변

8

memcpy의 문제는 아닙니다.

  1. float은 printf와의 ...을 통해 전달하는 경우에 allways double로 변환됩니다, 그래서 당신은 인텔 아키텍처의 대부분 4 바이트를 얻을 수 없습니다.
  2. 이 코드에서 0xdeadbeef을 실행하면 아키텍처가 BIG 엔디안이라고 가정합니다. 예를 들어 Intel x86과 같은 많은 리틀 엔디안 아키텍처가 있습니다.
+0

은 16 진수 부분의 printf 문제라는 것을 인식하지 못했습니다. 플로트가 제대로 두 번 캐스팅되지 않았 음을 이해하지 못합니다. – Tanj

+1

float를 double로 캐스팅하는 것이 4 바이트를 오른쪽으로 이동하는 것 이상입니다. 변환으로 float에서 3.14가 3.14를 두 배로 만듭니다. 그리고 판촉을 두 번 올린 후 printf()는 4 바이트를 전달합니다. 여기에서 % x은 2 바이트를 기대합니다. 따라서 % x 이후의 모든 것은 기지 밖입니다. – Andomar

6

printf()와 같은 변수 매개 변수 함수에 float가 전달되면 double이 승격된다는 것을 알고 계십니까? 그래서 당신은 말할 때 : 당신이 (내가 믿는) 제공이 4 바이트 값처럼 정말이 8 바이트 값이 무엇인지 치료에 정의되지 않은 동작을 시도하고

printf("bytes 0x%x float %e\n", flt, flt); 

.

2

"% x"는 printf에서 부호없는 int를 필요로합니다. 당신은 자동적으로 변환되고있는 플로트 (float)를주고 있습니다. 그것은 당신이 원하는 것이 아닙니다. 당신은 같은 것을하고 싶지 :

printf("bytes 0x%x float %e\n", *((unsigned int *)&flt), flt); 

아, 그리고 사람으로 다른 사람이 86에 있다면 더 0xefbeadde처럼을 0xdeadbeef 참조하지 않을거야, 지적했다.

1

이가 더 좋은 경우 참조 :

printf("bytes 0x%x float %e\n", *(int *)&flt, flt); 
1

이 매개 변수 프로모션을 두 배로 플로트에서 선언을 변경합니다. 내 컴퓨터에서 그 내용은 다음과 같이 인쇄됩니다.

bytes 0xefbeadde float -1.860545e+230 

0xefbeadde는 deadbeaf의 빅 엔디안입니다.double의 마지막 4 바이트는 정의되지 않으므로 float 이후에 표시되는 숫자는 다양합니다.

당신은 다른 컴퓨터에서 작동한다고 언급했는데 어떤 종류의 컴퓨터입니까? sizeof (float) == sizeof (double) : 작은 엔디안이어야합니다.

관련 문제