#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", a);
return 0;
}
그것은 표시 0
! 어떻게 가능합니까? 이유는 무엇입니까?
나는 일부러 넣어 가지고 %d
에서 printf
의 동작을 연구하기 위해 문 printf
.
답변:
%d
는 기대 int
하지만 플로트를 제공 했기 때문 입니다.
%e
/ %f
/ %g
를 사용 하여 플로트를 인쇄합니다.
0이 인쇄되는 이유 : 부동 소수점 숫자가로 double
전송되기 전에 로 변환 됩니다 printf
. 리틀 엔디안의 이중 표현에서 숫자 1234.5는 다음과 같습니다.
00 00 00 00 00 4A 93 40
A %d
는 32 비트 정수를 사용하므로 0이 인쇄됩니다. (테스트 printf("%d, %d\n", 1234.5f);
로 출력을 얻을 수 있습니다 0, 1083394560
.)
printf의 프로토 타입이 6.5.2.2/7에서 로 float
변환 된 이유는double
int printf(const char*, ...)
함수 프로토 타입 선언자의 줄임표 표기법으로 인해 마지막으로 선언 된 매개 변수 이후에 인수 유형 변환이 중지됩니다. 기본 인수 승격은 후행 인수에서 수행됩니다.
그리고 6.5.2.2/6부터,
호출 된 함수를 나타내는 표현식에 프로토 타입이 포함되지 않은 유형이있는 경우 정수 승격은 각 인수에 대해 수행되고 유형
float
이 있는 인수 는로 승격됩니다double
. 이를 기본 인수 승격 이라고합니다 .
(이것을 찾아 주신 Alok에게 감사드립니다.)
printf
가변 인수 함수, 표준은 가변 기능, A가 있다고 float
변환됩니다 double
전달하기 전에.
printf()
하면 Undefined Behavior 가 호출 됩니다.
기술적으로 더이 말하기하지 , 각 라이브러리 구현 자체, 따라서, 연구 노력하는 당신의 방법 이 많이 사용 될 수 없습니다 무엇을하고 있는지 수행하여 행동의. 시스템에서 의 동작을 연구하려고 할 수 있습니다. 그렇다면 문서를 읽고 소스 코드를 살펴보아야합니다. printf
printf
printf
printf
라이브러리에서 사용할 수 있는지 합니다.
예를 들어, Macbook에서 1606416304
프로그램과 함께 출력 을 얻습니다 .
즉, a float
를 가변 함수에 float
전달할 때는 double
. 그래서, 당신의 프로그램이 선언 한에 해당 a
A와 double
.
의 바이트를 조사하려면 다음 답변을double
볼 수 있습니다. 여기에서 최근 질문에 대한 을 .
그걸하자:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
unsigned char *p = (unsigned char *)&a;
size_t i;
printf("size of double: %zu, int: %zu\n", sizeof(double), sizeof(int));
for (i=0; i < sizeof a; ++i)
printf("%02x ", p[i]);
putchar('\n');
return 0;
}
위의 프로그램을 실행하면 다음과 같은 결과가 나타납니다.
size of double: 8, int: 4
00 00 00 00 00 4a 93 40
따라서의 처음 4 바이트는 double
0으로 판명되었으며, 이것이 호출 0
의 출력으로 얻은 이유 일 수 있습니다 printf
.
더 흥미로운 결과를 위해 프로그램을 약간 변경할 수 있습니다.
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
int b = 42;
printf("%d %d\n", a, b);
return 0;
}
Macbook에서 위의 프로그램을 실행하면 다음과 같은 결과가 나타납니다.
42 1606416384
Linux 시스템에서 동일한 프로그램을 사용하면 다음을 얻습니다.
0 1083394560
int
인수가 인수와 다른 레지스터에서 전달 되기 때문일 것 double
입니다. printf
with %d
는 int
42 라는 인수를 취하고 %d
두 번째 int
인수 는 두 번째 인수 가 없기 때문에 아마도 쓰레기를 인쇄합니다 .
%d
지정 알려줍니다 printf
정수를 기대 할 수 있습니다. 따라서 float의 처음 4 개 (또는 플랫폼에 따라 2 개) 바이트는 정수로 해석됩니다. 0이면 0이 인쇄됩니다.
1234.5의 이진 표현은 다음과 같습니다.
1.00110100101 * 2^10 (exponent is decimal ...)
float
실제로 IEEE754 이중 값으로 나타내는 C 컴파일러를 사용 하면 바이트가됩니다 (실수하지 않은 경우).
01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000
endianess가 거의없는 Intel (x86) 시스템 (즉, 최하위 바이트가 먼저 오는)에서는이 바이트 시퀀스가 반전되어 처음 4 바이트가 0이됩니다. 즉, printf
인쇄되는 것은 ...
IEEE754에 따른 부동 소수점 표현 은 이 Wikipedia 기사 를 참조하십시오 .
이진법의 부동 소수점 표현 때문입니다. 정수로 변환하면 0이 남습니다.
관련 데이터 유형 (int, float, string 등)과 함께 적절한 형식 지정자 (% d, % f, % s 등)를 사용하기 만하면됩니다.
정수가 아닙니다. 을 사용해보십시오 %f
.