Что такое time_t в конечном итоге typedef?

Вопрос: Я искал свою коробку Linux и увидел этот typedef: typedef __time_t time_t; Но я не смог найти определение __time_t. Лучший ответ: time_t Статья в Википедии в статье проливает свет на это. Суть в том, что тип time_t не гарантируется в спецификации C. Тип данных time_t - это тип данных в библиотека ISO C, определенная

Вопрос:

Я искал свою коробку Linux и увидел этот typedef:

typedef __time_t time_t;

Но я не смог найти определение __time_t.

Лучший ответ:

time_t Статья в Википедии в статье проливает свет на это. Суть в том, что тип time_t не гарантируется в спецификации C.

Тип данных time_t – это тип данных в библиотека ISO C, определенная для хранения системных значений времени. Такие значения возвращается из стандарта time()библиотечная функция. Этот тип typedef, определенный в стандарте  заголовок. ISO C определяет time_t как арифметический тип, но делает не указывать какой-либо конкретный тип, диапазон, разрешение или кодирование. Также неуказаны значения арифметические операции, применяемые ко времени значения.

Unix и POSIX-совместимые системы реализуют тип time_t как signed
integer (обычно 32 или 64 бита) который представляет количество секунд начиная с эпохи Unix
: полуночный UTC от 1 января 1970 года (не считая секунды прыжка). Некоторые системы правильно обрабатывать отрицательные значения времени, в то время как другие нет. Системы, использующие 32-разрядный тип time_t восприимчивы к Проблема 2038 года.

Ответ №1

[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 Ответ №2

стандарты

Уильям Брендель цитировал Википедию, но я предпочитаю ее изо рта лошади.

Проект стандарта 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: укажите язык C, поскольку входные данные поступают из стандартного ввода без расширения файла.
  • -include file: ” -include file файл, как если бы” #include “файл” “появился как первая строка первичного исходного файла”.
  • -: вход от стандартного ввода

Ответ №3

Ответ определенно специфичен для реализации. Чтобы узнать окончательно для вашей платформы/компилятора, просто добавьте этот вывод где-нибудь в свой код:

printf («sizeof time_t is: %dn», sizeof(time_t));

Если ответ равен 4 (32 бита), и ваши данные должны превышать 2038, вам потребуется 25 лет для переноса кода.

Ваши данные будут хорошими, если вы сохраните свои данные в виде строки, даже если это что-то простое:

FILE *stream = [stream file pointer that you’ve opened correctly]; fprintf (stream, «%dn», (int)time_t);

Затем просто прочитайте его так же (fread, fscanf и т.д. в int), и у вас есть время смещения вашего времени. Аналогичное обходное решение существует в .Net. Я пропускаю 64-разрядные номера эпох между системами Win и Linux без проблем (по каналу связи). Это вызывает проблемы с порядком байтов, но это другой предмет.

Чтобы ответить на запрос paxdiablo, я бы сказал, что он напечатал “19100”, потому что программа была написана таким образом (и я признаю, что я сделал это сам в 80-х):

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%02dn», local_date_time.tm_year);

Оператор printf печатает фиксированную строку “Год: 19”, за которой следует нулевая строка с “годами с 1900 года” (определение tm->tm_year). В 2000 году это значение равно 100. «%02d» прокладки с двумя нулями, но не обрезаются, если они длиннее двух цифр.

Правильный способ (изменить только на последнюю строку):

printf («Year is: %dn», local_date_time.tm_year + 1900);

Новый вопрос: какое обоснование для этого мышления?

Ответ №4

В Visual Studio 2008 по умолчанию используется __int64, если вы не определите _USE_32BIT_TIME_T. Вам лучше просто притворяться, что вы не знаете, как оно определено, поскольку оно может (и будет) изменяться с платформы на платформу.

Ответ №5

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 search.)

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; Ответ №6

Это 32-разрядный целочисленный тип со знаком на большинстве устаревших платформ. Однако это приводит к тому, что ваш код страдает от ошибки 2038 года. Таким образом, современные библиотеки C должны определять его как подписанный 64-битный int, который безопасен в течение нескольких миллиардов лет.

Ответ №7

Обычно вы найдете эти специфичные для конкретной реализации typedefs для gcc в каталоге заголовков bits или asm. Для меня это /usr/include/x86_64-linux-gnu/bits/types.h.

Вы можете просто grep или использовать вызов препроцессора, подобный предложенному Quassnoi, чтобы узнать, какой конкретный заголовок.

Ответ №8

К чему в конечном итоге относится type_t?

Надежный код не заботится о типе.

C разновидности time_t должны быть реальными типами, такими как double, long long, int64_t, int и т.д.

Он даже может быть unsigned как возвращаемые значения из многих временных функций, указывающих на ошибку, не являются -1, но (time_t)(-1) – этот вариант реализации является необычным.

Дело в том, что тип “нужно знать” встречается редко. Код должен быть написан, чтобы избежать необходимости.

Тем не менее, обычная “необходимость знать” возникает, когда код хочет напечатать необработанный time_t. Приведение к самому широкому целочисленному типу будет соответствовать большинству современных случаев.

time_t now = 0; time(&now); printf(«%jd», (intmax_t) now); // or printf(«%lld», (long long) now);

Приведение к double или long double тоже подойдет, но может дать неточный десятичный вывод

printf(«%.16e», (double) now); Ответ №9

time_t – это просто typedef для 8 байтов (long long/__int64), которые понимают все компиляторы и ОС. Еще в те дни он использовался только для long int (4 байта), но не сейчас. Если вы посмотрите на time_t в crtdefs.h, вы найдете обе реализации, но ОС будет использовать long long.

Оцените статью
Добавить комментарий