Time_t आखिरकार एक टाइप-सी क्या है?


जवाबों:


175

विकिपीडिया का लेख_ लेख इस पर कुछ प्रकाश डालता है। लब्बोलुआब यह है कि time_tसी विनिर्देश में प्रकार की गारंटी नहीं है।

time_tडेटाप्रकार आईएसओ सी पुस्तकालय प्रणाली समय मान संग्रहीत करने के लिए परिभाषित में एक डेटा प्रकार है। ऐसे मान मानक time() लाइब्रेरी फ़ंक्शन से वापस किए जाते हैं । यह प्रकार एक मानक हेडर में परिभाषित टाइपडिफ है। ISO C एक अंकगणितीय प्रकार के रूप में time_t को परिभाषित करता है, लेकिन इसके लिए कोई विशेष प्रकार , सीमा, संकल्प या एन्कोडिंग निर्दिष्ट नहीं करता है। अनिर्दिष्ट भी समय के मूल्यों पर लागू अंकगणितीय संचालन के अर्थ हैं।

यूनिक्स और पोसिक्स-कंप्लायंट सिस्टम time_tएक signed integer(आमतौर पर 32 या 64 बिट्स चौड़े) प्रकार को लागू करते हैं, जो यूनिक्स के शुरू होने के बाद से कुछ सेकंड की संख्या का प्रतिनिधित्व करता है : 1 जनवरी, 1970 की मध्यरात्रि यूटीसी (लीप सेकंड की गिनती नहीं)। कुछ सिस्टम नकारात्मक समय मानों को सही ढंग से संभालते हैं, जबकि अन्य नहीं करते हैं। 32-बिट time_tप्रकार का उपयोग करने वाले सिस्टम वर्ष 2038 समस्या के लिए अतिसंवेदनशील होते हैं ।


6
ध्यान दें, हालांकि, उस time_t मान आमतौर पर केवल मेमोरी में संग्रहीत होते हैं, डिस्क पर नहीं। इसके बजाय, time_t को पाठ या लगातार भंडारण के लिए कुछ अन्य पोर्टेबल प्रारूप में परिवर्तित किया जाता है। यह वास्तव में एक समस्या नहीं होने के लिए Y2038 समस्या बनाता है।

11
@ नीचे: एक विशिष्ट प्रणाली पर, जहां वही लोग ऑपरेटिंग सिस्टम और सी लाइब्रेरी बनाते हैं, time_tऑन-डिस्क डेटा संरचना का उपयोग करके हो सकता है। हालाँकि, चूंकि फाइलसिस्टम को अक्सर अन्य ऑपरेटिंग सिस्टम द्वारा पढ़ा जाता है, ऐसे कार्यान्वयन-निर्भर प्रकारों के आधार पर फाइल सिस्टम को परिभाषित करना मूर्खतापूर्ण होगा। उदाहरण के लिए, एक ही फाइल सिस्टम 32-बिट और 64-बिट सिस्टम दोनों पर उपयोग किया जा सकता है, और time_tआकार बदल सकता है। इस प्रकार, फाइलसिस्टम को अधिक सटीक रूप से परिभाषित करने की आवश्यकता है ("32-बिट हस्ताक्षरित पूर्णांक देने वाले सेकंड की संख्या, 1970 की शुरुआत के बाद से, यूटीसी में") केवल की तुलना में time_t

1
नोट के रूप में: लिंक किया गया विकिपीडिया लेख हटा दिया गया है, और यह अब time.hसामग्री की सूची पर पुनर्निर्देशित करता है । यह लेख cppreference.com से लिंक करता है, लेकिन उद्धृत सामग्री कहीं नहीं पाई जा सकती है ...
Michał Górny

3
@ माइकेलग्रनी: जब तक लेखों को नहीं हटाया जाता, तब तक आप सही संस्करण को खोजने के लिए इतिहास पर एक नज़र डाल सकते हैं।
जीटा

4
-1; विकिपीडिया के हवाले से दावा किया गया है कि POSIX गारंटी देता है कि time_tवह हस्ताक्षरित है। pubs.opengroup.org/onlinepubs/9699919799/basedefs/… यह बताता है कि विभिन्न चीजों में "हस्ताक्षरित पूर्णांक प्रकार" या "अहस्ताक्षरित पूर्णांक प्रकार" होना चाहिए, लेकिन time_tयह केवल यह कहता है कि यह "पूर्णांक प्रकार होगा" । एक कार्यान्वयन time_tअहस्ताक्षरित हो सकता है और अभी भी POSIX- अनुरूप हो सकता है।
मार्क अमेरी

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;

इसके $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
मैं दोनों को देखता हूं typedef __int32_t __time_t;और typedef __time_t time_t;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। आपके परिणाम स्पष्ट रूप से लिनक्स (जैसे कम से कम 2.6.32-5-xen-amd64 पर डेबियन से) में सेट किए गए हैं।
ssice

1
एक फ़ाइल बनाने के बिना एक लाइनर के साथ @Viet भी संभव है: stackoverflow.com/a/36096104/895245
Ciro Santilli 郝海东 with with 事件

1
क्यों के लिए grep __time_tऔर नहीं time_tकी अंतर्निहित प्रकार खोजने के लिए time_t? एक कदम आगे बढ़ाना?
chux -

@ chux-ReinstateMonica - ओपी ने कहा कि उसने time_t से __time_t तक का टाइफाइड ढूंढ लिया था। यह उत्तर केवल __time_t के रूप में परिभाषित किए गए प्रश्न को संबोधित कर रहा है। लेकिन मैं मानता हूं कि एक सामान्य मामले के लिए (जहां time_t को __time_t पर टाइप नहीं किया जा सकता है), आपको पहले time_t के लिए grep करने की आवश्यकता होगी, और फिर संभवतः उस रिटर्न के लिए फिर से grep करना होगा
माइकल फिरोज

@ मिचेलफिरथ मेला काफी। मुझे अपनी चिंता याद है typedef __time_t time_t;, भले ही ओपी ने पाया हो , आसपास के कोड की परीक्षा में यह सुनिश्चित करने की भी आवश्यकता है कि टाइपफेड वास्तव में इस्तेमाल किया गया था और न केवल एक सशर्त संकलन का हिस्सा था। typedef long time_t;शायद मिल भी गया हो।
चक्स -

30

मानक

विलियम ब्रेंडल ने विकिपीडिया को उद्धृत किया, लेकिन मैं इसे घोड़े के मुंह से पसंद करता हूं।

C99 N1256 मानक ड्राफ्ट 7.23.1 / 3 "समय के घटक" कहते हैं:

घोषित प्रकार size_t (7.17 में वर्णित) घड़ी_टी और time_t हैं जो अंकगणितीय प्रकार हैं जो समय का प्रतिनिधित्व करने में सक्षम हैं

और 6.2.5 / 18 "प्रकार" कहते हैं:

पूर्णांक और फ्लोटिंग प्रकारों को सामूहिक रूप से अंकगणितीय प्रकार कहा जाता है।

POSIX 7 sys_types.h कहता है:

[CX] time_t पूर्णांक प्रकार होगा।

जहां [CX]है के रूप में परिभाषित :

[सीएक्स] आईएसओ सी मानक के लिए विस्तार।

यह एक विस्तार है क्योंकि यह एक मजबूत गारंटी देता है: फ्लोटिंग पॉइंट्स बाहर हैं।

एक-लाइनर

क्वासोई द्वारा बताई गई फ़ाइल बनाने की आवश्यकता नहीं है :

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 "फ़ाइल" "प्राथमिक स्रोत फ़ाइल की पहली पंक्ति के रूप में दिखाई दी।"
  • -: स्टड से इनपुट

1
इको से पाइप की कोई आवश्यकता नहीं:gcc -E -xc -include time.h /dev/null | grep time_t
rvighne

12

उत्तर निश्चित रूप से कार्यान्वयन-विशिष्ट है। अपने प्लेटफ़ॉर्म / कंपाइलर के लिए निश्चित रूप से जानने के लिए, इस आउटपुट को अपने कोड में कहीं जोड़ें:

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

तो बस इसे उसी तरह से वापस पढ़ें (फ़्रेड, fscanf, आदि को एक इंट में), और आपके पास अपने समय की भरपाई का समय है। .Net में एक समान वर्कअराउंड मौजूद है। मैं विन और लिनक्स सिस्टम के बीच 64-बिट युग संख्या को बिना किसी समस्या के (एक संचार चैनल पर) पास करता हूं। यह बाइट-ऑर्डर करने के मुद्दों को लाता है, लेकिन यह एक और विषय है।

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%02d\n", local_date_time.tm_year);

printf"1900 के बाद से वर्ष" के साथ एक शून्य गद्देदार स्ट्रिंग हो (की परिभाषा: बयान तय स्ट्रिंग "19 साल है" प्रिंट tm->tm_year)। 2000 में, यह मान 100 है, जाहिर है। "%02d"दो शून्य के साथ पैड, लेकिन दो अंकों से अधिक समय तक नहीं काटता है।

सही तरीका है (केवल अंतिम पंक्ति में परिवर्तन):

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

नया सवाल: उस सोच के लिए तर्क क्या है?


2
आपको संभवतः %zuप्रारूप size_tमानों का उपयोग प्रारूप मानों के अनुसार करना चाहिए (जैसा sizeofकि उनके द्वारा दिया गया है ), क्योंकि वे अहस्ताक्षरित हैं ( u) और लंबाई size_t ( z) ·
एड्रियन गुंटर

... या उपयोग printf ("sizeof time_t is: %d\n", (int) sizeof(time_t));और zमुद्दे से बचें ।
chux -

6

विजुअल स्टूडियो 2008 के तहत, यह __int64परिभाषित करता है जब तक कि आप परिभाषित नहीं करते _USE_32BIT_TIME_T। आप केवल दिखावा करने से बेहतर हैं कि आप यह नहीं जानते कि इसे किस रूप में परिभाषित किया गया है, क्योंकि यह प्लेटफॉर्म से प्लेटफॉर्म में बदल सकता है (और करेगा)।


2
यह आमतौर पर काम करता है, लेकिन अगर आपका कार्यक्रम उन चीजों का ट्रैक रखने के लिए है जो अब से 30 साल बाद होंगे, तो यह बहुत महत्वपूर्ण है कि आपके पास 32-बिट time_t हस्ताक्षरित नहीं है।
रोब केनेडी

4
@ रब, बा, छोड़ो! हम सिर्फ 2036 में हेडलेस मुर्गियों की तरह दौड़ना शुरू करेंगे, जैसा कि हमने Y2K के लिए किया था। हम में से कुछ Y2k38 सलाहकार होने से पैसे की एक बाल्टी बनाएंगे, लियोनार्ड निमोय एक और प्रफुल्लित करने वाली किताब लाएंगे कि कैसे हम सभी को जंगल में जाकर छिपना चाहिए ...
paxdiablo

1
... और यह सब खत्म हो जाएगा, जनता सोच रही थी कि सभी उपद्रव के बारे में क्या था। मैं बच्चों की विरासत के लिए कुछ पैसे कमाने के लिए सेवानिवृत्ति से भी बाहर आ सकता हूं :-)।
paxdiablo

2
BTW, हमें केवल एक Y2K बग मिला और वह एक वेब पेज था जिसने दिनांक 1 जनवरी, 19100 को सूचीबद्ध किया। पाठक के लिए व्यायाम क्यों ...
paxdiablo

9
यदि 30 वर्षों में होने वाली घटना "इस बैकअप को समाप्त करें" है, तो आप अब मुसीबत में हो सकते हैं, 2038 में नहीं। आज के 32-बिट time_t में 30 साल जोड़ें, और आपको अतीत में एक तारीख मिलती है। आपका कार्यक्रम ईवेंट को प्रोसेस करने के लिए देखता है, एक ऐसा है जो अतिदेय है (100 साल से!), और इसे निष्पादित करता है। उफ़, अब और बैकअप नहीं।
रॉब केनेडी

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 खोज का उपयोग करके शीर्ष लेख फ़ाइल में पाया जा सकता है।)

में 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;

उन फ़ाइलों को Ubuntu 15.10 BTW पर glibc द्वारा प्रदान किया गया है।
सिरो सेंटिल्ली 郝海东 冠状 iro i 法轮功 '19

3
यह long intहर जगह नहीं है। देखें stackoverflow.com/questions/384502/…
Zan Lynx

4

यह अधिकांश विरासत प्लेटफार्मों पर एक 32-बिट हस्ताक्षरित पूर्णांक प्रकार है। हालाँकि, इससे आपका कोड वर्ष 2038 बग से पीड़ित होगा । इसलिए आधुनिक सी लाइब्रेरीज़ को इसके बजाय एक हस्ताक्षरित 64-बिट इंट होने के लिए परिभाषित किया जाना चाहिए, जो कुछ अरब वर्षों के लिए सुरक्षित है।


3

आमतौर पर आप इन अंतर्निहित कार्यान्वयन-विशिष्ट टाइपिडिफ को gcc bitsया asmहेडर डायरेक्टरी में देख पाएंगे । मेरे लिए, यह है/usr/include/x86_64-linux-gnu/bits/types.h

आप केवल विशिष्ट grep को देख सकते हैं, या उस तरह के प्रीप्रोसेसर इनविटेशन का उपयोग कर सकते हैं, जो Quassnoi द्वारा सुझाया गया है कि कौन से विशिष्ट शीर्ष लेख देखें।


1

आखिरकार एक time_t typedef क्या है?

रोबस्ट कोड को परवाह नहीं है कि प्रकार क्या है।

सी प्रजातियाँ 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);

मुझे स्थिति जानने की आवश्यकता है क्योंकि मुझे एआरएम प्रणाली से एएमडी 64 सिस्टम में समय स्थानांतरित करने की आवश्यकता है। time_t बांह पर 32 बिट्स और सर्वर पर 64 बिट्स है। अगर मैं समय को एक प्रारूप में अनुवाद करता हूं, और एक स्ट्रिंग भेजता हूं, तो यह अक्षम और धीमा है। इसलिए यह बेहतर है कि केवल पूरे time_t को भेजें और इसे सर्वर के अंत में क्रमित करें। हालाँकि, मुझे टाइप को थोड़ा और समझने की जरूरत है क्योंकि मैं नहीं चाहता कि नंबर सिस्टम के बीच अलग-अलग धीरज से उलझ जाए, इसलिए मुझे htonl का उपयोग करने की आवश्यकता है ... लेकिन सबसे पहले, मुझे आधार जानने की आवश्यकता है, मैं चाहता हूं अंतर्निहित प्रकार का पता लगाने के लिए;)
उल्लू

एक और "जानने की जरूरत है" मामला, कम से कम हस्ताक्षरित बनाम अहस्ताक्षरित के लिए है कि क्या आपको समय घटाते समय ध्यान रखना चाहिए। यदि आप केवल "परिणाम घटाते और प्रिंट करते हैं", तो आप संभवतः एक हस्ताक्षरित time_t के साथ एक सिस्टम पर जो उम्मीद करेंगे, वह मिलेगा, लेकिन अहस्ताक्षरित time_t के साथ नहीं।
माइकल फर्थ

@MichaelFirth मामले दोनों पूर्णांक हस्ताक्षर किए गए समय_ और अहस्ताक्षरित time_t के लिए मौजूद हैं जहां कच्चे घटाव अप्रत्याशित परिणाम देगा। सी double difftime(time_t time1, time_t time0)एक समान घटाव दृष्टिकोण के लिए प्रदान करता है ।
चक्स -

-3

time_tसिर्फ typedef8 बाइट्स ( long long/__int64) के लिए है, जो सभी कंपाइलर और ओएस को समझते हैं। वापस दिनों में, यह केवल long int(4 बाइट्स) के लिए हुआ करता था, लेकिन अब नहीं। आप को देखो, तो time_tमें crtdefs.hआप दोनों कार्यान्वयन मिलेगा लेकिन ओएस का उपयोग करेगा long long


5
सभी संकलक और OSes? नहीं, मेरे लिनक्स सिस्टम पर कंपाइलर 4 बाइट्स पर हस्ताक्षरित कार्यान्वयन लेता है।
विन्सेंट

Zynq पर 7010 सिस्टम time_t 4bytes है।
उल्लू

1
एम्बेडेड सिस्टम पर मैं time_t पर काम करता हूं लगभग हमेशा 32-बिट्स या 4 बाइट्स। मानक विशेष रूप से बताता है कि यह विशिष्ट कार्यान्वयन है जो इस उत्तर को केवल गलत बनाता है।
कोबसुवे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.