Yanıtlar:
Time_t Wikipedia makalesi makale bu konuda bazı ışık tutuyor. Sonuç time_t
olarak, C spesifikasyonunda tipinin garanti edilmemesi.
time_t
Veri 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 standarttime()
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_t
tü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 bittime_t
türü kullanan sistemler , 2038 Yılı sorununa duyarlıdır .
time_t
disk ü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_t
boyutu 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
.
time.h
içerik listesine yönlendirilmektedir . Bu makale cppreference.com sitesine bağlantı veriyor, ancak belirtilen içerik hiçbir yerde bulunamadı…
time_t
imzalanmış 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_t
yalnızca "tamsayı türü" olacağını belirtir . Bir uygulama time_t
imzasız olabilir ve yine de POSIX uyumlu olabilir.
[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
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).
__time_t
ve değil ? Bir adımı atlıyor musunuz? time_t
time_t
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.
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 girdigcc -E -xc -include time.h /dev/null | grep time_t
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?
%zu
, biçimlendiriciyi size_t
değ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
printf ("sizeof time_t is: %d\n", (int) sizeof(time_t));
da z
sorunu kullanın ve önleyin .
Visual Studio 2008 altında, __int64
siz 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.
time_t
long int
64 bit makinelerde tip , aksi halde long long int
.
Bunu aşağıdaki başlık dosyalarında doğrulayabilirsiniz:
time.h
: /usr/include
types.h
ve 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;
long int
yerde değil . Bkz. Stackoverflow.com/questions/384502/…
Ç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.
Genellikle gcc için uygulamaya özel bu typedef'leri bits
veya asm
header dizininde bulabilirsiniz. Benim için öyle /usr/include/x86_64-linux-gnu/bits/types.h
.
Hangi üstbilgiyi görmek için sadece Quassnoi tarafından önerilen gibi bir önişlemci çağrısı kullanabilir veya kullanabilirsiniz .
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 unsigned
hata 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 double
veya 'ya yayınlamak da long double
işe yarar , ancak hatalı ondalık çıktı sağlayabilir
printf("%.16e", (double) now);
double difftime(time_t time1, time_t time0)
muntazam bir çıkarma yaklaşımı sağlar.
time_t
tüm derleyicilerin ve işletim sistemlerinin anladığı sadece typedef
8 bayt ( long long/__int64
) içindir. Eskiden, sadece long int
(4 bayt) içindi ama şimdi değil. Eğer bakarsanız time_t
içinde crtdefs.h
size iki uygulamaları bulacaksınız ama OS kullanacak long long
.
long int
.