Respostas:
O artigo do artigo time_t da Wikipedia lança alguma luz sobre isso. A linha inferior é que o tipo de time_t
não é garantido na especificação C.
O
time_t
tipo de dados é um tipo de dados na biblioteca ISO C definido para armazenar valores de hora do sistema. Esses valores são retornados datime()
função de biblioteca padrão . Este tipo é um typedef definido no cabeçalho padrão. O ISO C define time_t como um tipo aritmético, mas não especifica nenhum tipo , intervalo, resolução ou codificação específica para ele. Também não são especificados os significados das operações aritméticas aplicadas aos valores temporais.Os sistemas compatíveis com Unix e POSIX implementam o
time_t
tipo como umsigned integer
(geralmente com largura de 32 ou 64 bits) que representa o número de segundos desde o início da época do Unix : meia-noite UTC de 1 de janeiro de 1970 (sem contar os segundos bissextos). Alguns sistemas lidam corretamente com valores de tempo negativos, enquanto outros não. Os sistemas que usam umtime_t
tipo de 32 bits são suscetíveis ao problema do ano 2038 .
time_t
a estrutura de dados em disco. No entanto, como os sistemas de arquivos são frequentemente lidos por outros sistemas operacionais, seria tolo definir o sistema de arquivos com base nesses tipos dependentes da implementação. Por exemplo, o mesmo sistema de arquivos pode ser usado em sistemas de 32 e 64 bits e time_t
pode mudar de tamanho. Portanto, os sistemas de arquivos precisam ser definidos com mais precisão ("número inteiro assinado de 32 bits que fornece o número de segundos desde o início de 1970, no UTC") do que apenas time_t
.
time.h
conteúdos. Esse artigo tem um link para cppreference.com, mas o conteúdo citado não é encontrado em nenhum lugar…
time_t
está assinado está incorreta. pubs.opengroup.org/onlinepubs/9699919799/basedefs/… determina que várias coisas devem ser um "tipo inteiro assinado" ou "tipo inteiro não assinado", mas time_t
diz apenas que "deve ser um tipo inteiro" . Uma implementação pode deixar de ser time_t
assinada e ainda ser compatível com 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;
É definido $INCDIR/bits/types.h
através de:
# 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;
e typedef __time_t time_t;
em um 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
. Seus resultados são explicitamente definidos como no Linux (pelo menos no 2.6.32-5-xen-amd64 do Debian).
__time_t
e não time_t
encontrar o tipo subjacente de time_t
? Omitindo um passo?
typedef __time_t time_t;
, o exame do código ao redor também é necessário para garantir que o typedef foi de fato usado e não apenas parte de uma compilação condicional. typedef long time_t;
pode ter sido encontrado também.
Padrões
William Brendel citou a Wikipedia, mas eu prefiro da boca do cavalo.
O rascunho padrão C99 N1256 7.23.1 / 3 "Componentes do tempo" diz:
Os tipos declarados são size_t (descrito em 7.17) clock_t e time_t, que são tipos aritméticos capazes de representar tempos
e 6.2.5 / 18 "Tipos" diz:
Tipos inteiros e flutuantes são chamados coletivamente de tipos aritméticos.
[CX] time_t deve ser um tipo inteiro.
onde [CX]
é definido como :
[CX] Extensão ao padrão ISO C.
É uma extensão porque oferece uma garantia mais forte: os pontos flutuantes estão fora.
liner gcc
Não há necessidade de criar um arquivo como mencionado por Quassnoi :
echo | gcc -E -xc -include 'time.h' - | grep time_t
No Ubuntu 15.10 GCC 5.2, as duas principais linhas são:
typedef long int __time_t;
typedef __time_t time_t;
Divisão de comando com algumas citações de man gcc
:
-E
: "Pare após o estágio de pré-processamento; não execute o compilador adequadamente."-xc
: Especifique o idioma C, uma vez que a entrada vem do stdin que não possui extensão de arquivo.-include file
: "Processar arquivo como se" #include "file" "aparecesse como a primeira linha do arquivo de origem primário."-
: entrada de stdingcc -E -xc -include time.h /dev/null | grep time_t
A resposta é definitivamente específica da implementação. Para descobrir definitivamente sua plataforma / compilador, basta adicionar esta saída em algum lugar do seu código:
printf ("sizeof time_t is: %d\n", sizeof(time_t));
Se a resposta for 4 (32 bits) e seus dados forem além de 2038 , você terá 25 anos para migrar seu código.
Seus dados ficarão bem se você os armazenar como uma string, mesmo que seja algo simples como:
FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);
Depois, leia-o da mesma maneira (fread, fscanf etc. em um int) e você terá o tempo de compensação da época. Uma solução semelhante existe no .Net. Eu passo números de época de 64 bits entre os sistemas Win e Linux sem problemas (em um canal de comunicação). Isso traz problemas de ordem de bytes, mas esse é outro assunto.
Para responder à consulta de paxdiablo, eu diria que ele imprimiu "19100" porque o programa foi escrito dessa maneira (e admito que eu mesmo fiz isso nos anos 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%02d\n", local_date_time.tm_year);
A printf
instrução imprime a sequência fixa "O ano é: 19" seguida por uma sequência preenchida com zero com os "anos desde 1900" (definição de tm->tm_year
). Em 2000, esse valor é 100, obviamente. "%02d"
pads com dois zeros, mas não trunca se tiver mais de dois dígitos.
A maneira correta é (mude para a última linha apenas):
printf ("Year is: %d\n", local_date_time.tm_year + 1900);
Nova pergunta: qual é a justificativa para esse pensamento?
%zu
especificador de formato para o formato de size_t
valores (como gerados pelo sizeof
), como eles não são assinados ( u
) e de size_t length ( z
) ·
printf ("sizeof time_t is: %d\n", (int) sizeof(time_t));
e evite o z
problema.
No Visual Studio 2008, o padrão é um, a __int64
menos que você defina _USE_32BIT_TIME_T
. É melhor você fingir que não sabe como é definido, pois ele pode (e vai) mudar de plataforma para plataforma.
time_t
é do tipo long int
em máquinas de 64 bits, caso contrário, é long long int
.
Você pode verificar isso nestes arquivos de cabeçalho:
time.h
: /usr/include
types.h
e typesizes.h
:/usr/include/x86_64-linux-gnu/bits
(As instruções abaixo não são uma após a outra. Elas podem ser encontradas no respetivo arquivo de cabeçalho usando a pesquisa Ctrl + f.)
1) Em time.h
typedef __time_t time_t;
2) Em types.h
# define __STD_TYPE typedef
__STD_TYPE __TIME_T_TYPE __time_t;
3) Em 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) Novamente em 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
todo lugar. Veja stackoverflow.com/questions/384502/…
Normalmente, você encontrará esses typedefs específicos de implementação subjacentes para o gcc no diretório bits
ou asm
header. Para mim é /usr/include/x86_64-linux-gnu/bits/types.h
.
Você pode apenas grep ou usar uma chamada de pré - processador como a sugerida por Quassnoi para ver qual cabeçalho específico.
Em última análise, para que serve um time_t typedef?
Código robusto não se importa com o tipo.
Espécies C time_t
para ser um tipo real como double, long long, int64_t, int
, etc.
Pode até ser unsigned
como os valores de retorno de muitas funções de tempo indicando erro -1
, mas (time_t)(-1)
- Esta opção de implementação é incomum.
O ponto é que a "necessidade de conhecer" o tipo é rara. O código deve ser escrito para evitar a necessidade.
No entanto, uma "necessidade de saber" comum ocorre quando o código deseja imprimir o raw time_t
. A conversão para o tipo inteiro mais amplo acomoda os casos mais modernos.
time_t now = 0;
time(&now);
printf("%jd", (intmax_t) now);
// or
printf("%lld", (long long) now);
A conversão para um double
ou long double
também funcionará, mas pode fornecer uma saída decimal inexata
printf("%.16e", (double) now);
double difftime(time_t time1, time_t time0)
uma abordagem de subtração uniforme.
time_t
é apenas typedef
para 8 bytes ( long long/__int64
) que todos os compiladores e sistemas operacionais entendem. Antigamente, costumava ser apenas por long int
(4 bytes), mas não agora. Se você olhar para time_t
dentro crtdefs.h
, encontrará as duas implementações, mas o sistema operacional será usado long long
.
long int
.