2011-09-20 4 views
14

나는 C Programming Language, 2nd Edition을 읽음으로써 C를 배우려고합니다. 나는 약간의 프로그래밍 경험을 가지고 있지만 C.% d가 printf에서 사용될 때 float 변수는 어떻게됩니까?

와 나는 제 1 장에서 현재 아니에요 나는 다음과 같은 코드가 있습니다 :

A: 0.000000 B: 0.15 
A: 1.100000 B: 1.25 
A: 2.200000 B: 2.35 

:


float f; 
    for (f = 0.0; f <= 3; f += 1.1) 
     printf("A: %3f B: %6.2f\n", f, f + 0.15); 

그것은 출력을 인쇄 괜찮아.

printf("A: %3d B: %6.2f\n", f, f + 0.15); 

새로운 출력

A: 0 B: 0.00 
A: -1610612736 B: 0.00 
A: -1610612736 B: -625777476808257557292155887552002761191109083510753486844893290688350183831589633800863219712.00 

여기에 무슨이다 다음과 같이


는 지금은 printf와 변경? % d를 사용했기 때문에 float가 int로 변환 될 것으로 예상되지만 그 일은 발생하지 않았습니다. 또한, 왜 B 값이 잘못 되었습니까? 여기 무슨 일이 있었던거야?

+2

int로 변환하라는 요청을하지 않았지만 ** int!라고했습니다. 쓰레기 입력, 쓰레기 출력. –

답변

15

당신이 전화했을 때 :

printf("A: %3d B: %6.2f\n", f, f + 0.15); 

C가 자동으로 doublefloat 값을 변환 (그것이 int printf(const char *fmt, ...);과 같이 가변 인수를 사용하는 함수를 호출 할 때 표준 변환. 논쟁을 위해서, 우리는 sizeof(int)이 4이고 sizeof(double)이 8이라고 가정 할 것입니다. 예외는 있지만, 그것들은 아주 적습니다.

따라서 호출은 스택에 포인터를 밀어 넣었으며 f의 경우 8 바이트, 그리고 f + 0.15의 경우 8 바이트를 더했습니다. 형식 문자열을 처리 할 때 %dprintf()에게 형식 문자열 다음에 4 바이트의 int을 스택에 넣었다 고 알려줍니다. 그것이 당신이 한 것이 아니기 때문에 정의되지 않은 동작을 호출했습니다. 다음에 일어나는 일은 C 표준에 따라 OK입니다.

그러나 가장 가능성있는 구현은 blithely 4 바이트를 읽어서 int 인 것처럼 인쇄합니다 (사용자가 진실이라고 말하면 신뢰합니다). 그런 다음 %6.2f 형식을 사용합니다. 그것은 스택에서 8 바이트를 double으로 읽습니다. 이로 인해 잘못 정렬 된 액세스에 대한 메모리 오류가 발생할 가능성이 있습니다 (SPARC와 같이 8 바이트 경계에 double이 정렬되어야하는 64 비트 시스템이 필요합니다). 또는 4 바이트를 읽습니다. ff + 0.15의 4 바이트를 조합하여 예기치 않은 double 값을 만듭니다.

+0

좋은 대답이므로'printf ("A : % d % d B : % 6.2", ...'잘못된 A 값은 얻지 만 B는 영향을받지 않습니다. –

+1

상당수의 가정하에, 예 이 동작은 완전히 정의되지 않았지만 실제로는 그렇습니다. –

8

Printf는 지시 한대로 메모리를 처리합니다. 진행되는 전환이 없습니다. float를 나타내는 메모리를 int로 취급합니다. 두 가지가 다르게 저장되기 때문에 본질적으로 난수가됩니다.

당신이 출력 정수로 당신의 플로트를하려면 먼저 캐스팅해야합니다

printf("A: %3d B: %6.2f\n", (int)f, f + 0.15); 
+1

좋습니다. 그래서 int로 캐스팅하지 않았기 때문에 f의 값이 변경 되었습니까? 그렇지 않다면 printf의 두 번째 부분이 % 6.2f를 사용하고 있기 때문에 atleast가 올바른 값을 가져야합니까? – Gollum

관련 문제