이 프로그램은 어떻게 작동합니까?
#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
전송되기 전에 로 CHAPTER 2 됩니다 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부터,
된 함수를 호출 나타내는 표현식에 프로토-type이 포함되지 않은 유형이있는 경우 정수 승격은 각 인수에 대해 수행되고 유형
float
이 있는 인수 는로 승격됩니다double
. 이를 기본 인수 승격 이라고합니다 .
(이것을 찾아 주신 Alok에게 감사드립니다.)
기술적으로 더이 말하기하지 , 각 라이브러리 구현 자체, 따라서, 연구 노력하는 당신의 방법 이 많이 사용되는 것이 무엇인지 수행하여 행동의. 시스템에서 의 동작을 연구 할 수 있습니다. 본 설명서를 읽고 라이브러리에서 사용할 수있는 소스 코드를 볼 수 있습니다. 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
%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이 남습니다.
정의되지 않은 동작을 호출했기 때문에 : 매개 변수 유형에 대해 거짓말을하여 printf () 메서드의 계약을 위반 했으므로 컴파일러는 원하는대로 자유롭게 수행 할 수 있습니다. 프로그램 출력을 "dksjalk is a ninnyhead !!!"로 만들 수 있습니다. 기술적으로는 여전히 옳습니다.
그 이유는 printf()
꽤 멍청한 기능이기 때문입니다 . 유형을 전혀 확인하지 않습니다. 첫 번째 인수가라고 말하면 int
(그리고 이것이 당신이 말하는 것입니다 %d
), 그것은 당신을 믿고 int
. 이 경우 컴퓨터가 4 바이트 int
와 8 바이트 double
( 내부 float
로 변환 됨)를 사용한다고 가정하면 의 처음 4 바이트는 0이되고 인쇄됩니다.double
printf()
a
자동으로 부동 소수점을 정수로 변환하지 않습니다. 둘 다 저장 형식이 다르기 때문입니다. 따라서 변환하려면 (int) typecasting을 사용하십시오.
#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", (int)a);
return 0;
}
C ++로 태그를 지정 했으므로이 코드 는 예상대로 변환을 수행합니다.
#include <iostream.h>
int main() {
float a = 1234.5f;
std::cout << a << " " << (int)a << "\n";
return 0;
}
산출:
1234.5 1234
%d
십진수
%f
플로트
부동 소수점과 정수가 다르게 표현되기 때문에 0이됩니다.
관련 데이터 유형 (int, float, string 등)과 함께 적절한 형식 지정자 (% d, % f, % s 등)를 사용하기 만하면됩니다.
% d이 아닌 % f를 원합니다
헤이 그것은 무언가를 인쇄해야했기 때문에 0을 인쇄했습니다. C 0은 다른 모든 것임을 기억하십시오!
정수가 아닙니다. 을 사용해보십시오 %f
.
참고 URL : https://stackoverflow.com/questions/2377733/how-does-this-program-work
'IT' 카테고리의 다른 글
grunt throw "Recursive process.nextTick detected" (0) | 2020.09.08 |
---|---|
git diff 두 파일을 동일한 분기, 동일한 커밋 (0) | 2020.09.08 |
두 개의 개의 연결 목록이 병합 확인하십시오. (0) | 2020.09.08 |
EditText, 외부 터치에 대한 명확한 증가 (0) | 2020.09.08 |
AppDelegate에서 UINavigationBar 배경색을 변경하는 방법 (0) | 2020.09.08 |