답변:
time_t 위키 백과 문서의 문서에서는이에 대한 몇 가지 빛이 나고. 결론 time_t
은 C 사양에서 유형이 보장되지 않는다는 것입니다.
time_t
데이터 유형이 시스템 타임 값을 저장하기 위해 정의 된 ISO C 라이브러리의 데이터 형식이다. 이러한 값은 표준time()
라이브러리 함수 에서 반환됩니다 . 이 유형은 표준 헤더에 정의 된 typedef입니다. ISO C는 time_t를 산술 유형으로 정의하지만 특정 유형 , 범위, 해상도 또는 인코딩을 지정하지는 않습니다 . 시간 값에 적용되는 산술 연산의 의미도 지정되어 있지 않습니다.유닉스 및 POSIX 호환 시스템 은 유닉스 시대가 시작된 이래 초 수를 나타내는 (일반적으로 32 또는 64 비트 폭)
time_t
유형을 구현합니다signed integer
( 1970 년 1 월 1 일 자정 UTC (윤초 계산 제외)). 일부 시스템은 음의 시간 값을 올바르게 처리하지만 다른 시스템은 그렇지 않습니다. 32 비트time_t
유형을 사용하는 시스템 은 2038 년 문제에 취약합니다 .
time_t
하는 경우 온 디스크 데이터 구조를 사용하여 발생할 수 있습니다. 그러나 파일 시스템은 종종 다른 운영 체제에서 읽으므로 구현에 따라 다른 유형에 따라 파일 시스템을 정의하는 것은 어리석은 일입니다. 예를 들어, 동일한 파일 시스템이 32 비트 및 64 비트 시스템 모두에서 사용될 수 있으며 time_t
크기가 변경 될 수 있습니다. 따라서 파일 시스템은 다음과 같이보다 정확하게 정의해야합니다 ( "1970 년 시작 이후 32 초 부호있는 정수 (UTC)") time_t
.
time.h
컨텐츠 목록으로 리디렉션됩니다 . 해당 기사의 링크 cppreference.com하지만 인용 된 콘텐츠는 아무데도 ... 발견 할 수있다
time_t
가 서명 한 것을 보증한다고 Wikipedia에서 인용 한 주장 이 잘못되었습니다. pubs.opengroup.org/onlinepubs/9699919799/basedefs/… 는 다양한 것들이 "부호있는 정수형"또는 "부호없는 정수형"이어야 한다고 지시하지만, time_t
단지 "정수형이어야한다" 고 말합니다 . 구현은 time_t
서명되지 않고 POSIX 호환이 될 수 있습니다.
[root]# cat time.c
#include <time.h>
int main(int argc, char** argv)
{
time_t test;
return 0;
}
[root]# gcc -E time.c | grep __time_t
typedef long int __time_t;
다음을 $INCDIR/bits/types.h
통해 정의됩니다 .
# 131 "/usr/include/bits/types.h" 3 4
# 1 "/usr/include/bits/typesizes.h" 1 3 4
# 132 "/usr/include/bits/types.h" 2 3 4
typedef __int32_t __time_t;
과 typedef __time_t time_t;
A의 FreeBSD freebsd-test 8.2-RELEASE-p2 FreeBSD 8.2-RELEASE-p2 #8: Sun Aug 7 18:23:48 UTC 2011 root@freebsd-test:/usr/obj/usr/src/sys/MYXEN i386
. 결과는 Linux에서 명시 적으로 설정됩니다 (Debian의 2.6.32-5-xen-amd64 이상).
__time_t
하지 time_t
의 기본 유형을 찾기 위해 time_t
? 단계를 생략?
typedef __time_t time_t;
typedef가 실제로 사용되고 조건부 컴파일의 일부가 아니라는 것을 보장하기 위해 주변 코드의 검사도 필요하다고 생각합니다. typedef long time_t;
발견되었을 수도 있습니다.
표준
윌리엄 브렌델 (William Brendel) 은 Wikipedia를 인용했지만, 나는 말의 입에서 그것을 선호합니다.
C99 N1256 표준 초안 7.23.1 / 3 "시간 요소" 는 다음과 같이 말합니다.
선언 된 타입은 size_t (7.17에서 설명) clock_t와 time_t로 시간을 표현할 수있는 산술 타입입니다.
및 6.2.5 / 18 "종류"는 말합니다 :
정수 및 부동 유형을 통칭하여 산술 유형이라고합니다.
POSIX 7 sys_types.h 는 다음과 같이 말합니다.
[CX] time_t는 정수 타입이어야한다.
어디는 [CX]
되고 정의 :
[CX] ISO C 표준으로의 확장.
부동 소수점이 더 강력하다는 것을 보증하기 때문에 확장입니다.
gcc 원 라이너
Quassnoi가 언급 한대로 파일을 만들 필요가 없습니다 .
echo | gcc -E -xc -include 'time.h' - | grep time_t
Ubuntu 15.10 GCC 5.2에서 두 줄은 다음과 같습니다.
typedef long int __time_t;
typedef __time_t time_t;
따옴표로 묶은 명령 분석 man gcc
:
-E
: "전처리 단계 후 중지하고 컴파일러를 올바르게 실행하지 마십시오."-xc
: 파일 확장자가없는 stdin에서 입력이 이루어 지므로 C 언어를 지정하십시오.-include file
: ""#include "file" "이 기본 소스 파일의 첫 번째 줄로 나타난 것처럼 파일을 처리하십시오."-
: stdin에서 입력gcc -E -xc -include time.h /dev/null | grep time_t
답은 구현에 따라 다릅니다. 플랫폼 / 컴파일러에 대해 확실하게 알아 보려면 코드의 어딘가에이 출력을 추가하십시오.
printf ("sizeof time_t is: %d\n", sizeof(time_t));
답이 4 (32 비트)이고 데이터가 2038을 넘어서는 경우 25 년 동안 코드를 마이그레이션해야합니다.
데이터가 다음과 같은 간단한 경우에도 데이터를 문자열로 저장하면 데이터가 좋습니다.
FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);
그런 다음 같은 방식으로 다시 읽습니다 (fread, fscanf 등을 정수로), epoch 오프셋 시간이 있습니다. .Net에도 비슷한 해결 방법이 있습니다. Windows와 Linux 시스템간에 64 비트 에포크 번호를 전달합니다 (통신 채널을 통해). 바이트 순서 문제가 발생하지만 다른 주제입니다.
paxdiablo의 질문에 답하기 위해 프로그램이 이런 식으로 작성 되었기 때문에 "19100"이 인쇄되었다고 말하고 싶습니다.
time_t now;
struct tm local_date_time;
now = time(NULL);
// convert, then copy internal object to our object
memcpy (&local_date_time, localtime(&now), sizeof(local_date_time));
printf ("Year is: 19%02d\n", local_date_time.tm_year);
그만큼 printf
명령문은 고정 문자열 "Year is : 19"와 "1900 이후 연도"(정의 tm->tm_year
) 로 채워진 0으로 채워진 문자열을 인쇄합니다 . 2000 년에는 분명히 그 가치가 100입니다. "%02d"
두 개의 0으로 채워지지만 두 자리보다 길면 잘리지 않습니다.
올바른 방법은 (마지막 줄로만 변경)입니다.
printf ("Year is: %d\n", local_date_time.tm_year + 1900);
새로운 질문 : 그 사고에 대한 이론적 근거는 무엇입니까?
%zu
형식으로 size_t
값을 지정 하려면 형식 지정자를 사용해야합니다.sizeof
u
z
printf ("sizeof time_t is: %d\n", (int) sizeof(time_t));
하고 피하십시오 z
.
Visual Studio 2008에서는 기본적으로 __int64
를 정의하지 않으면_USE_32BIT_TIME_T
. 플랫폼에서 플랫폼으로 변경할 수 있기 때문에 정의 된 내용을 모르는 척하는 것이 좋습니다.
time_t
long int
64 비트 시스템에서 유형 이며 그렇지 않은 경우입니다 long long int
.
다음 헤더 파일에서이를 확인할 수 있습니다.
time.h
: /usr/include
types.h
및 typesizes.h
:/usr/include/x86_64-linux-gnu/bits
(아래 문장들은 차례 차례가 아닙니다. Ctrl + f 검색을 사용하여 resp. 헤더 파일에서 찾을 수 있습니다.)
1)에서 time.h
typedef __time_t time_t;
2)에서 types.h
# define __STD_TYPE typedef
__STD_TYPE __TIME_T_TYPE __time_t;
3)에서 typesizes.h
#define __TIME_T_TYPE __SYSCALL_SLONG_TYPE
#if defined __x86_64__ && defined __ILP32__
# define __SYSCALL_SLONG_TYPE __SQUAD_TYPE
#else
# define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
#endif
4) 다시 types.h
#define __SLONGWORD_TYPE long int
#if __WORDSIZE == 32
# define __SQUAD_TYPE __quad_t
#elif __WORDSIZE == 64
# define __SQUAD_TYPE long int
#if __WORDSIZE == 64
typedef long int __quad_t;
#else
__extension__ typedef long long int __quad_t;
long int
어디에나 있지는 않습니다 . 참조 stackoverflow.com/questions/384502/...
대부분의 레거시 플랫폼에서 32 비트 부호있는 정수 유형입니다. 그러나 코드가 2038 년 버그 로 고통받습니다 . 따라서 현대 C 라이브러리는 대신 부호있는 64 비트 int로 정의해야하며 이는 수십 년 동안 안전합니다.
일반적으로 bits
또는 asm
헤더 디렉토리 에서 gcc에 대한 기본 구현 별 typedef를 찾을 수 있습니다. 나를 위해, 그것은/usr/include/x86_64-linux-gnu/bits/types.h
입니다.
Quassnoi가 제안한 것과 같은 전 처리기 호출을 사용하여 특정 헤더를 확인할 수 있습니다.
궁극적으로 time_t typedef는 무엇입니까?
강력한 코드는 유형이 무엇인지 신경 쓰지 않습니다.
C 종은 time_t
할 수 진짜 형 처럼 double, long long, int64_t, int
, 등
심지어 수 unsigned
많은 시간 함수의 리턴 값은 오류가없는 표시로 -1
하지만,(time_t)(-1)
-이 구현 선택은 드물다.
요점은 "알아야 할 필요"유형이 드물다는 것입니다. 필요를 피하기 위해 코드를 작성해야합니다.
그러나 코드가 raw를 인쇄하려고 할 때 일반적인 "알아야 할 필요"가 발생합니다 time_t
. 가장 넓은 정수 유형으로 캐스팅하면 대부분의 최신 사례를 수용 할 수 있습니다.
time_t now = 0;
time(&now);
printf("%jd", (intmax_t) now);
// or
printf("%lld", (long long) now);
에 캐스팅 double
하거나 long double
작동하지만 정확하게 10 진 출력을 제공 할 수 있음
printf("%.16e", (double) now);
double difftime(time_t time1, time_t time0)
균일 한 빼기 방법을 제공합니다 .
time_t
그냥 typedef
8 바이트 (에 대한 long long/__int64
모든 컴파일러 및 OS의 이해). 옛날에는 long int
(4 바이트) 였지만 지금은 아닙니다. time_t
in 을 보면 crtdefs.h
두 가지 구현을 모두 찾을 수 있지만 OS가 사용 long long
합니다.
long int
.