Time_t nihayetinde bir typedef nedir?


Yanıtlar:


175

Time_t Wikipedia makalesi makale bu konuda bazı ışık tutuyor. Sonuç time_tolarak, C spesifikasyonunda tipinin garanti edilmemesi.

time_tVeri türü sistem zamanı değerleri depolamak için tanımlandığı ISO C kütüphanesinde bir veri türüdür. Bu değerler standart time() kütüphane işlevinden döndürülür . Bu tür, standart üstbilgide tanımlanan bir typedef'tir. ISO C, time_t öğesini aritmetik bir tür olarak tanımlar, ancak bunun için belirli bir tür , aralık, çözünürlük veya kodlama belirtmez. Ayrıca zaman değerlerine uygulanan aritmetik işlemlerin anlamları da belirtilmemiş.

Unix ve POSIX uyumlu sistemler, time_ttürü signed integer, Unix döneminin başlamasından bu yana geçen saniye sayısını temsil eden (genellikle 32 veya 64 bit genişliğinde) olarak uygular : 1 Ocak 1970 gece yarısı UTC (artık saniye saymaz). Bazı sistemler negatif zaman değerlerini doğru işlerken, diğerleri yapmaz. 32 bit time_ttürü kullanan sistemler , 2038 Yılı sorununa duyarlıdır .


6
Bununla birlikte, time_t değerlerinin diskte değil, genellikle yalnızca bellekte saklandığını unutmayın. Bunun yerine, time_t kalıcı depolama için metne veya başka bir taşınabilir biçime dönüştürülür. Bu, Y2038 problemini gerçekten bir problem haline getirmez.

11
@Heath: aynı kişilerin işletim sistemini ve C kitaplığını oluşturduğu belirli bir sistemde, time_tdisk üzerinde veri yapısında kullanılabilir. Ancak, dosya sistemleri genellikle diğer işletim sistemleri tarafından okunduğundan, dosya sistemini bu tür uygulamaya bağlı türlere göre tanımlamak saçma olur. Örneğin, aynı dosya sistemi hem 32 bit hem de 64 bit sistemlerde kullanılabilir ve time_tboyutu değişebilir. Bu nedenle, dosya sistemlerinin tam olarak tanımlanması gerekir ("1970 bitinin başlangıcından bu yana UTC sayısını saniye cinsinden veren 32 bit işaretli tam sayı") time_t.

1
Not olarak: bağlantılı Wikipedia makalesi kaldırılmıştır ve şimdi time.hiçerik listesine yönlendirilmektedir . Bu makale cppreference.com sitesine bağlantı veriyor, ancak belirtilen içerik hiçbir yerde bulunamadı…
Michał Górny

3
@ MichałGórny: Düzeltildi, makaleler silinmediği sürece doğru sürümü bulmak için her zaman geçmişe bakabilirsiniz.
Zeta

4
1; Wikipedia'dan POSIX'in time_timzalanmış olduğunu garanti ettiği iddia yanlıştır. pubs.opengroup.org/onlinepubs/9699919799/basedefs/… , çeşitli şeylerin "işaretli tam sayı türü" veya "işaretsiz tam sayı türü" olması gerektiğini belirtir, ancak time_tyalnızca "tamsayı türü" olacağını belirtir . Bir uygulama time_timzasız olabilir ve yine de POSIX uyumlu olabilir.
Mark Amery

112

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

Şununla tanımlanır $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

1
Ben de görmek typedef __int32_t __time_t;ve typedef __time_t time_t;bir de 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. Sonuçlarınız açıkça Linux'ta bu şekilde ayarlanmıştır (en azından Debian'dan 2.6.32-5-xen-amd64 üzerinde).
ssice

1
@Viet, bir dosya oluşturmadan tek bir astarla da mümkündür: stackoverflow.com/a/36096104/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

1
Neden altta yatan türü bulmak için grep __time_tve değil ? Bir adımı atlıyor musunuz? time_ttime_t
chux - Monica'yı geri yükle

@ chux-ReinstateMonica - OP time_t ile __time_t arasında typedef'i bulduğunu söyledi. Bu cevap sadece __time_t ifadesinin ne olarak tanımlandığı sorusunu ele alıyor. Ancak, genel bir durum için (time_t'ın __time_t olarak yazılmayabileceği durumlarda), önce time_t için grep ve daha sonra geri dönen şey için tekrar grep yapmanız gerektiğini kabul ediyorum
Michael Firth

@MichaelFirth Fuarı yeterince. OP bulduğum halde typedef __time_t time_t;, yalnızca koşullu bir derlemenin bir parçası değil, typedef'in gerçekten kullanıldığından emin olmak için çevre kodunun incelenmesi de endişemi hatırlıyorum . typedef long time_t;olabilir de.
chux - Monica'yı

31

Standartlar

William Brendel Wikipedia'dan alıntı yaptı, ama atın ağzından tercih ederim.

C99 N1256 standart taslak 7.23.1 / 3 "Zamanın bileşenleri" diyor:

Bildirilen türler, zamanları temsil edebilen aritmetik türler olan size_t (7.17'de açıklanmıştır) clock_t ve time_t şeklindedir.

ve 6.2.5 / 18 "Türler" diyor:

Tam sayı ve kayan türlere toplu olarak aritmetik türler denir.

POSIX 7 sys_types.h diyor ki:

[CX] time_t bir tamsayı türü olmalıdır.

burada [CX]şu şekilde tanımlanır :

[CX] ISO C standardına genişletildi.

Bu bir uzantıdır çünkü daha güçlü bir garanti verir: kayan noktalar dışarıda.

gcc tek astarlı

Quassnoi tarafından belirtildiği gibi bir dosya oluşturmaya gerek yok :

echo | gcc -E -xc -include 'time.h' - | grep time_t

Ubuntu 15.10 GCC 5.2'de ilk iki satır:

typedef long int __time_t;
typedef __time_t time_t;

Bazı alıntılarla komut dökümü man gcc:

  • -E: "Önişleme aşamasından sonra durun; derleyiciyi düzgün çalıştırmayın."
  • -xc: Girdi dosya uzantısı olmayan stdin'den geldiğinden, C dilini belirtin.
  • -include file: "Dosyayı birincil kaynak dosyasının ilk satırı olarak" #include "file" "gibi görünüyor."
  • -: stdin'den girdi

1
gcc -E -xc -include time.h /dev/null | grep time_t
Yankıdan

12

Cevap kesinlikle uygulamaya özeldir. Platformunuz / derleyiciniz için kesin olarak öğrenmek için, bu çıktıyı kodunuzda bir yere eklemeniz yeterlidir:

printf ("sizeof time_t is: %d\n", sizeof(time_t));

Cevap 4 (32 bit) ise ve verileriniz 2038'in ötesine geçecekse , kodunuzu taşımak için 25 yılınız vardır.

Aşağıdaki gibi basit bir şey olsa bile verilerinizi dize olarak saklarsanız verileriniz iyi olur:

FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);

Sonra aynı şekilde tekrar okuyun (int, fscanf, vb. İnt) ve dönem ofset zamanınız var. Benzer bir çözüm .Net. 64-bit dönem sayılarını Win ve Linux sistemleri arasında sorunsuz bir şekilde iletiyorum (bir iletişim kanalı üzerinden). Bu, bayt sıralaması sorunlarını gündeme getiriyor, ancak bu başka bir konu.

Paxdiablo'nun sorgusunu cevaplamak için, programın bu şekilde yazıldığı için "19100" yazdığını söyleyebilirim (ve bunu 80'lerde kendim yaptığımı itiraf ediyorum):

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"1900 yılından bu yana yıllar" ile sıfır dolgulu dize izledi (tanımı: deyim sabit dize "19 Yıl ise" yazdırır tm->tm_year). 2000 yılında bu değer 100'dür. "%02d"iki sıfırla doldurur, ancak iki basamaktan uzunsa kesilmez.

Doğru yol (yalnızca son satıra geç):

printf ("Year is: %d\n", local_date_time.tm_year + 1900);

Yeni soru: Bu düşüncenin mantığı nedir?


2
Büyük olasılıkla %zu, biçimlendiriciyi size_tdeğerleri ( biçimlendirildiği gibi sizeof) biçimlendirmek için, işaretsiz ( u) ve uzunluk_t ( z) · uzunluğunda olduğu için kullanmalısınız
Adrian Günter

... ya printf ("sizeof time_t is: %d\n", (int) sizeof(time_t));da zsorunu kullanın ve önleyin .
chux - Monica'yı

6

Visual Studio 2008 altında, __int64siz tanımlamadığınız sürece varsayılan olarak bir _USE_32BIT_TIME_T. Platformdan platforma değişebileceği (ve değişeceği) için ne olarak tanımlandığını bilmiyormuş gibi davranmanız daha iyi olur.


2
Bu genellikle işe yarar, ancak programınız bundan 30 yıl sonra gerçekleşecek şeyleri takip etmek istiyorsa , imzalı bir 32 bit time_t'ye sahip olmamanız oldukça önemlidir .
Rob Kennedy

4
@Rob, bah, bırak! 2036'da başsız tavuklar gibi koşmaya başlayacağız, Y2K için yaptığımız gibi. Bazılarımız Y2k38 danışmanlarından bir kova dolusu para kazanacağız, Leonard Nimoy hepimizin ormanda nasıl saklanıp saklanacağımızla ilgili başka bir komik kitap ortaya çıkaracak ...
paxdiablo

1
... ve her şey patlayacak, halk tüm yaygara hakkında ne olduğunu merak ediyor. Hatta çocukların miras :-) için biraz para kazanmak için emeklilik gelebilir.
paxdiablo

2
BTW, sadece bir Y2K hatası bulduk ve bu tarihi 1 Ocak 19100 olarak listeleyen bir web sayfasıydı. Neden okuyucuya yönelik egzersiz yapın ...
paxdiablo

9
30 yıl içinde gerçekleşecek olan olay "bu yedeklemenin geçerliliğini yitir" ise, 2038'de değil, ŞİMDİ belada olabilirsiniz. Bugünün 32 bit time_t'ına 30 yıl ekleyin ve geçmişte bir tarih alırsınız. Programınız işlenecek olayları arar, gecikmiş olanı bulur (100 yıla kadar!) Ve yürütür. Hata! Artık yedekleme yok.
Rob Kennedy

5

time_tlong int64 bit makinelerde tip , aksi halde long long int.

Bunu aşağıdaki başlık dosyalarında doğrulayabilirsiniz:

time.h: /usr/include
types.hve typesizes.h:/usr/include/x86_64-linux-gnu/bits

(Aşağıdaki ifadeler birbiri ardına değildir. Ctrl + f araması kullanılarak ilgili başlık dosyasında bulunabilirler.)

1) 'de time.h

typedef __time_t time_t;

2) 'de types.h

# define __STD_TYPE     typedef  
__STD_TYPE __TIME_T_TYPE __time_t;  

3) 'de 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) Yine 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;

Bu dosyalar Ubuntu 15.10 BTW'de glibc tarafından sağlanır.
Ciro Santilli

3
Her long intyerde değil . Bkz. Stackoverflow.com/questions/384502/…
Zan Lynx

4

Çoğu eski platformda 32 bit imzalı bir tamsayı türüdür. Ancak, bu kod 2038 yıl hata muzdarip neden olur . Bu yüzden modern C kütüphaneleri, bunun yerine 64 milyar int imzalı bir 64 bit int olarak tanımlanmalıdır.



1

Sonuçta bir time_t typedef nedir?

Sağlam kod, türün ne olduğunu umursamıyor.

C türleri gibi gerçektime_t bir tür olmak vb. double, long long, int64_t, int

Hatta unsignedhata olmadığını gösteren birçok zaman fonksiyonunun dönüş değerleri gibi olabilir -1, ama (time_t)(-1)- Bu uygulama seçimi nadirdir.

Mesele şu ki, "bilinmesi gerekenler" türü nadirdir. İhtiyaçtan kaçınmak için kod yazılmalıdır.


Ancak, kod ham yazdırmak istediğinde yaygın bir "bilinmesi gerek" oluşur time_t. En geniş tamsayı türüne döküm, en modern vakaları barındırır.

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

Bir doubleveya 'ya yayınlamak da long doubleişe yarar , ancak hatalı ondalık çıktı sağlayabilir

printf("%.16e", (double) now);

Durumu bilmem gerekiyor çünkü bir ARM sisteminden AMD64 sistemine zaman aktarmam gerekiyor. time_t kolda 32 bit ve sunucuda 64 bittir. zamanı bir formata çevirir ve bir dize gönderirsem verimsiz ve yavaş olur. Bu nedenle, tüm time_t dosyasını göndermek ve sunucu tarafında sıralamak çok daha iyidir. Ancak, türü biraz daha anlamalıyım çünkü sayının sistemler arasındaki farklı endianiteye göre karışmasını istemiyorum, bu yüzden htonl kullanmalıyım ... ama önce, bilmek zorundayım, istiyorum altta yatan türü bulmak;)
Baykuş

En azından imzalı ve imzasız olanlar için başka bir "bilmeye gerek" vakası, zamanları çıkarırken dikkat etmeniz gerekip gerekmediğidir. Sadece "sonucu çıkarır ve yazdırırsanız", imzalı bir time_t içeren ancak imzasız bir time_t içeren bir sistemde beklediğiniz şeyi alırsınız.
Michael Firth

@MichaelFirth Vakalar, ham çıkarımın beklenmedik sonuçlara yol açacağı hem tamsayı işaretli time_t hem de işaretsiz time_t için mevcuttur. C sağlardouble difftime(time_t time1, time_t time0) muntazam bir çıkarma yaklaşımı sağlar.
chux - Monica'yı

-3

time_ttüm derleyicilerin ve işletim sistemlerinin anladığı sadece typedef8 bayt ( long long/__int64) içindir. Eskiden, sadece long int(4 bayt) içindi ama şimdi değil. Eğer bakarsanız time_tiçinde crtdefs.hsize iki uygulamaları bulacaksınız ama OS kullanacak long long.


5
tüm derleyiciler ve işletim sistemleri? Hayır. Linux sistemimde derleyici 4 bayt imzalı uygulamayı alır.
Vincent

Zynq 7010 sistemlerinde time_t 4 bayttır.
Baykuş

1
Yerleşik sistemlerde time_t üzerinde çalıştığım neredeyse her zaman 32 bit veya 4 bayttır. Standart, özellikle bu cevabı yanlış yapan uygulamaya özel olduğunu belirtmektedir.
Cobusve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.