IT

이 프로그램은 어떻게 작동합니까?

lottoking 2020. 9. 8. 08:15
반응형

이 프로그램은 어떻게 작동합니까?


#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변환 된 이유는doubleint printf(const char*, ...)

선언 선언 선언자의 줄임표 표기법으로 선언 될 인수 유형 된 선언 변수 이후에 선언이 중지됩니다. 기본 인수 승격은 후행 인수에서 수행됩니다.

그리고 6.5.2.2/6부터,

된 함수를 호출 나타내는 표현식에 프로토-type이 포함되지 않은 유형이있는 경우 정수 승격은 각 인수에 대해 수행되고 유형 float있는 인수 는로 승격됩니다 double. 이를 기본 인수 승격 이라고합니다 .

(이것을 찾아 주신 Alok에게 감사드립니다.)


기술적으로 더이 말하기하지 , 각 라이브러리 구현 자체, 따라서, 연구 노력하는 당신의 방법 이 많이 사용되는 것이 무엇인지 수행하여 행동의. 시스템에서 의 동작을 연구 할 수 있습니다. 본 설명서를 읽고 라이브러리에서 사용할 수있는 소스 코드를 볼 있습니다. printfprintfprintfprintf

예를 들어, Macbook에서 1606416304프로그램과 함께 출력 얻습니다 .

즉, a 는를 float가변 함수에 즉, float거기 double있습니다. 그래서, 당신의 프로그램이 선언 한에 해당 aA와 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 개의 바이트는 double0으로 판명 결과, 호출 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 ...)

floatIEEE754 이중 값으로 대규모 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이되고 인쇄됩니다.doubleprintf()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

반응형