[c] time_t는 궁극적으로 typedef 무엇입니까?

Linux 상자를 검색하고 다음 typedef를 보았습니다.

typedef __time_t time_t;

그러나 나는 그 __time_t 정의를 찾을 수 없었다 .



답변

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 년 문제에 취약합니다 .


답변

[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


답변

표준

윌리엄 브렌델 (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에서 입력

답변

답은 구현에 따라 다릅니다. 플랫폼 / 컴파일러에 대해 확실하게 알아 보려면 코드의 어딘가에이 출력을 추가하십시오.

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);

새로운 질문 : 그 사고에 대한 이론적 근거는 무엇입니까?


답변

Visual Studio 2008에서는 기본적으로 __int64 를 정의하지 않으면_USE_32BIT_TIME_T . 플랫폼에서 플랫폼으로 변경할 수 있기 때문에 정의 된 내용을 모르는 척하는 것이 좋습니다.


답변

time_tlong int64 비트 시스템에서 유형 이며 그렇지 않은 경우입니다 long long int.

다음 헤더 파일에서이를 확인할 수 있습니다.

time.h: /usr/include
types.htypesizes.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;


답변

대부분의 레거시 플랫폼에서 32 비트 부호있는 정수 유형입니다. 그러나 코드가 2038 년 버그 로 고통받습니다 . 따라서 현대 C 라이브러리는 대신 부호있는 64 비트 int로 정의해야하며 이는 수십 년 동안 안전합니다.