printf를 사용하여 clock_t를 인쇄하는 올바른 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1083142

  •  23-08-2019
  •  | 
  •  

문제

나는 현재 명시적인 캐스트를 사용하고 있습니다 unsigned long long 그리고 사용 %llu 인쇄하지만 그 이후로 size_t has the %z 지정자, 그렇지 않은 이유 clock_t 하나가 있습니까?

그것에 대한 매크로도 없습니다. 어쩌면 x64 시스템 (OS 및 CPU)에서 size_t 길이가 8 바이트입니다 (이 경우에도 제공했습니다. %z),하지만 어때요 clock_t?

도움이 되었습니까?

해결책

완벽한 방법이없는 것 같습니다. 문제의 근원은 그 것입니다 clock_t 정수 또는 부동 소수점 일 수 있습니다.

Clock_t는 부동 소수점 유형 일 수 있습니다

처럼 Bastien Léonard는 언급합니다 posix (그에게 upvote), C99 N1256 초안 7.23.1/3도 다음과 같이 말합니다.

clock_t는] 시간을 나타낼 수있는 산술 유형

및 6.2.5/18 :

정수 및 부동 유형은 총체적으로 산술 유형이라고합니다.

표준은 산술 유형을 정수 또는 부동 소수점 유형으로 정의합니다.

clocks_per_sec으로 나눌 경우 Long Double을 사용하십시오.

반환 값 clock() 구현이 정의되어 있으며 표준 의미를 얻는 유일한 방법은 CLOCKS_PER_SEC 몇 초를 찾으려면 :

clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));

이것은 다음 두 가지 이유로 완벽하지는 않지만 충분합니다.

  • 아날로그가없는 것 같습니다 intmax_t 부동 소수점 유형 : 가장 큰 정밀 플로팅 포인트 데이터 유형의 구현 및 Printf 지정자를 얻는 방법은 무엇입니까? 따라서 내일 더 큰 부동 소수점 유형이 나오면 사용하여 구현을 중단 할 수 있습니다.

  • 만약에 clock_t 정수, 플로트 캐스트는 가장 가까운 플로트를 사용하도록 잘 정의되어 있습니다. 당신은 정밀도를 잃을 수 있지만 절대 가치에 비해 그다지 중요하지 않으며 엄청난 시간 동안 만 발생합니다. long int x86에서는 64 비트 유의미한 80 비트 플로트이며 수백만 년이 지났습니다.

레모네이드를 가두십시오 누가 비슷한 말을 했어요.

정수라고 가정하면 %ju 및 uintmax_t를 사용하십시오.

하지만 unsigned long long 현재 가장 큰 표준 정수 유형입니다.

따라서 가능한 가장 큰 서명되지 않은 정수 유형에 타이핑하는 것이 가장 좋습니다.

#include <stdint.h>

printf("%ju", (uintmax_t)(clock_t)1);

uintmax_t 기계에서 가능한 가장 큰 정수 크기의 크기가 보장됩니다.

uintmax_t 그리고 Printf 지정자 %ju 예를 들어 C99 및 GCC에 도입되었습니다.

보너스로서, 이것은 한 번만 해결하고 안정적으로 방법에 대한 모든 질문에 대해 printf 정수 유형 (불행히도 반드시의 경우는 아닙니다. clock_t).

두 배라면 잘못 될 수있는 것 :

  • 정수, 정의되지 않은 행동에 맞지 않기에 너무 큰 경우
  • 1보다 훨씬 작고 0으로 반올림되면 아무것도 보지 못할 것입니다.

이러한 결과는 플로트 변환을위한 정수보다 훨씬 가혹하기 때문에 플로트를 사용하는 것이 더 나은 아이디어 일 것입니다.

GLIBC 2.21에서는 정수입니다

매뉴얼은 사용한다고 말합니다 double 더 나은 아이디어입니다 :

GNU/Linux 및 GNU/HURD 시스템에서 Clock_T는 Long Int와 동일하며 Clocks_per_Sec은 정수 값입니다. 그러나 다른 시스템에서는 clock_t와 macro clocks_per_sec 모두 정수 또는 부동 소수점 유형 일 수 있습니다. 위의 예에서와 같이 CPU 시간 값을 두 배로 캐스팅하면 산술 및 인쇄와 같은 작업이 기본 표현이 무엇인지에 관계없이 올바르게 일관되게 작동하는지 확인합니다.

GLIBC 2.21에서 :

또한보십시오

다른 팁

내가 아는 한, 당신이하는 방식이 최고입니다. 그것을 제외하고 clock_t 실제 유형 일 수 있습니다.

time_t 그리고 clock_t 정수 또는 실제 플로팅 유형이어야합니다.

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html

시계 진드기가 잘 정의 된 장치가 아니기 때문일 것입니다. 몇 초로 변환하여 두 배로 인쇄 할 수 있습니다.

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

clocks_per_sec 매크로는 1 초 안에 클럭 진드기 수를 나타내는 표현식으로 확장됩니다.

C 표준은 다양한 다양한 아키텍처를 수용해야하므로 내부 시계 유형이 산술이라는 사실을 제외하고는 더 이상 보장 할 수 없습니다.

대부분의 경우 시간 간격에 관심이 있으므로 시계 진드기의 차이를 밀리 초로 변환합니다. an unsigned long 32 비트 인 경우에도 거의 50 일의 간격을 나타 내기에 충분히 크므로 대부분의 경우에는 충분히 커야합니다.

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;

한 가지 방법은 사용하는 것입니다 gettimeofday 기능. 이 기능을 사용하여 차이를 찾을 수 있습니다.

unsigned long  diff(struct timeval second, struct timeval first)
{
    struct timeval  lapsed;
    struct timezone tzp;
    unsigned long t;

    if (first.tv_usec > second.tv_usec) {
        second.tv_usec += 1000000;
        second.tv_sec--;
    }

    lapsed.tv_usec = second.tv_usec - first.tv_usec;
    lapsed.tv_sec  = second.tv_sec  - first.tv_sec;
    t = lapsed.tv_sec*1000000 + lapsed.tv_usec;

    printf("%lu,%lu - %lu,%lu = %ld,%ld\n",
           second.tv_sec, second.tv_usec,
           first.tv_sec,  first.tv_usec,
           lapsed.tv_sec, lapsed.tv_usec);

    return t;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top