time_t的最大值(struct timespec)

时间:2011-04-11 07:08:46

标签: c linux time

我正在使用struct timespec结构,这里是:

struct timespec {
           time_t tv_sec;                /* Seconds */
           long   tv_nsec;               /* Nanoseconds */
};

事情是,用户将输入每个成员的值,我想要检查最多。用户可以输入的值。

我可以拿最大值吗? time_t的值为int max value? INT_MAX tv_secLONG_MAX tv_nsec(在limits.h中定义)time_t?两者的最低可接受值是多少?它是零吗?我猜不能接受负值?只需添加,这些值将在计时器中使用。

P.S:{{1}}的typedef在哪里?在time.h中找不到它。

9 个答案:

答案 0 :(得分:26)

由于此处的人们正在回答如何设置最大time_t值,并进一步猜测其类型,我想我会添加c++方式来执行此操作:

#include <limits>
...
time_t maxTime = std::numeric_limits<time_t>::max();

答案 1 :(得分:3)

time_t只是一个长整数 它在(在我的Ubuntu linux系统上)/usr/include/time.h中定义,但是该定义一直延伸到/usr/include/bits/types.h,其中__SLONGWORD_TYPE(这是{ {1}}定义为)已定义。

简单地检查一个值是否大于__TIME_T_TYPE的问题是,一旦某个值超过此值,它将自动回绕并变为负数。因此,您无法检查是否有任何值大于此值 - 宏被定义为此类型可以采用的最大值。

您并不真的希望用户输入这些值 - 除非“用户”是指“开发人员”。测试这个的唯一真正的“安全”方法是让用户输入一个字符串(当然是c风格),然后运行两个检查:
1)检查用户是否输入了多于允许的数字(便宜的技巧LONG_MAX来计算数字中的位数)。
2)如果这等于数字位数,则开始逐位比较。您可以使用一些模运算来逐位比较。

这是检查用户是否输入太大的数字的最安全的方法。你不会以这种方式遇到任何溢出问题,尽管 非常单调乏味。 希望这会有所帮助。

答案 2 :(得分:3)

我不太关心time_t的内容,而是关于什么是合理的。在我见过的任何系统上,time_t可以编码时间跨度从63年到10 11 年(几乎我所知道的每个系统都使用64位数字,因为这些天才提出来了在1999年的Y2K世界即将结束的事情中,当2038年过去时,谁会注意到更大的“事件”还有待观察。

如果您合理地期望您的程序将运行不超过50年,请拒绝任何大于50 * 365 * 86400的值,或者只是使该值饱和。我不认为我现在写的任何程序在50年内都会被使用(虽然我不会对此进行验证)。
另一方面,如果您的系统 使用32位time_t,那么无论如何都无关紧要,因为无论如何系统时间都会在50年内溢出,所以可以'无论如何都要构建一个有意义的时间而不会改变时代。

如果你问“你想暂停多久?”并且用户说“250年”,如果你说“是的,50也会做”,我认为这不是真正错误的程序行为。因为,嘿,差异确实是不可观察的。

答案 3 :(得分:2)

取自ISO/IEC 9899:TC3§7.23

  
      
  1. 声明的类型为size_t(在7.17中描述); clock_ttime_t是能够表示时间的算术类型;和   保存日历时间组件的struct tm,称为   破碎的时间。

  2.   
  3. clock_ttime_t中可表示的时间范围和精度是实现定义的

  4.   

因此,您无法根据C标准对其最大值进行任何假设。

如果您需要编写可移植代码,您可能会使用autotols。 Autoconf提供了AC_CHECK_SIZEOF宏,可以帮助您处理特定于体系结构的数据限制。

答案 4 :(得分:2)

不幸的是,ISO C标准(目前为C11)没有提供任何方法来获得time_t的最大值。因此,除非使用Autoconf提供信息等工具,否则需要做出一些假设。

假设time_t是没有填充位的整数类型(现在大多数平台就是这种情况,如果不是全部的话),可以采取:

(((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1

这是有符号整数类型的最大可表示值(但是time_t中的值可表示的事实并不意味着系统支持它作为time_t值。< / p>

还可能想要检测time_t是否为整数类型。 ISO C标准规定time_t是实际类型(条款7.27.1)。根据定义,真实类型是整数类型或实际浮动类型floatdoublelong double,以及如第6.11.1条所述,可能在标准的未来版本中添加其他版本。因此,如果time_t不是整数类型,则它必然是实数浮点类型。因此,可以使用测试time_t检测(time_t) 1 / 2 == 0是否为整数类型。

注意:如果(T) 1 / 2是浮动类型,则C标准并不严格要求T与0不同,但如果不是这种情况,我怀疑此类平台会出现严重问题用浮点计算。

答案 5 :(得分:1)

根据维基百科,time_t可以是整数或浮点数,但通常是32位或64位有符号整数。我认为您可以假设的最大安全值是INT_MAX。对于time_t,至少负数是合法的,并在1970年1月1日之前提及。

答案 6 :(得分:0)

对于LINUX,ctime可以接受任何time_t,它将使结果年份低于或等于INT_MAX限制,即对于64位系统:

time_t maxtime = 67767976233521999;
printf("%s\n", ctime(&maxtime));

将产生以下输出:Tue Dec 31 23:59:59 2147483647

答案 7 :(得分:0)

这应该为您提供任何 POSIX 机器和任何架构上 time_t 的最大值,只要 time_t 是无符号整数(非浮点)类型。它被写入与机器的字长和任何填充位无关。使用 cc -DDEBUG 编译以获得一些诊断信息:

#include <time.h>
#include <stdint.h>     /* uintmax_t */
#include <stdio.h>      /* fprintf() */
#include <limits.h>     /* CHAR_BIT, UINT_MAX */
#include <inttypes.h>   /* format spec PRIX64:
                         * ll/l + X on 32/64-bit arch */

/* The following two routines (should) work for any integer
 * representation in either 2's or 1's complement and for any
 * #bits per byte (CHAR_BIT could be <> 8).
 */

/* Count the bits set in any unsigned integer type (plus any signed
 * iff using 2's complement integer representation).
 * Returns the precision (width - padding bits - sign bit) iff given
 * the xxx_MAX value of any integer type, signed or unsigned.
 * From SEI CERT C Coding Standard:
 * Rules for Developing Safe, Reliable, and Secure Systems (2016)  
 */
size_t popcount (uintmax_t num)
{
    size_t cnt = 0;
    
    while (num != 0) {
        if (num % 2 == 1)
            cnt++;
        num >>= 1;
    }
    return cnt;
}
#define PRECISION(max_value)    popcount(max_value)
#define SIGN_BIT                (1)
#ifndef MIN
#define MIN(a, b)               ((a) < (b)? (a): (b))
#endif
/* Get the maximum value of a time_t from it's storage width.
 * On error: returns (time_t)(-1) iff time_t is longer than an 
 * intmax_t (which would mean it's a floating point type and
 * longer than an intmax_t).
 * ASSERTION: time_t is a signed integer type,
 * i.e. not (unsigned, but the bit pattern of (-1) treated special).  
 */
time_t get_time_t_max (void)
{
    time_t t0, t1 = (time_t)(-1);
    size_t size = sizeof(time_t);
    size_t prec;
    uintmax_t max;

    if (sizeof(time_t) > sizeof(uintmax_t))
        return t1;
  
    /* Get an uintmax_t with all bits set that could be in a time_t.
     * We can not do this calculation with a time_t as long we do
     * not know its precision (overflow could occur).
     */
    prec = MIN (PRECISION (UINTMAX_MAX), CHAR_BIT * sizeof(time_t));
    max = (uintmax_t) 1 << (prec - 1);
    max = max|(max - 1);

    t0 = max;       /* maybe truncation happens here */
  
    /* Now account for any padding bits */
    prec = PRECISION(t0) - SIGN_BIT;
    t0 = (time_t) 1 << (prec - 1);
    t1 = t0|(t0 - 1);
  
#ifdef DEBUG
    fprintf (stderr, "time_t_max\t= 0x%"PRIX64"\n", (uint64_t) t1);
    fprintf (stderr, "sizeof(time_t)\t= %3zd byte\n", size);
    fprintf (stderr, "precision\t= %3zd bit\n", prec);
    fprintf (stderr, "padding\t\t= %3zd bit\n",
                CHAR_BIT*size - prec - SIGN_BIT);
    fprintf (stderr, "bits per byte\t= %3d bit\n", CHAR_BIT);
#endif /* DEBUG */
    return t1;
}
#undef SIGN_BIT
/*! vi: set ai tabs=8 shiftwidth=4: */

答案 8 :(得分:-1)

# include <sys/time.h>
# include <time.h>
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h> /* printf() */
# include <inttypes.h>  /* format spec PRIX64: ll/l + X on 32/64-bit arch */
# include <limits.h>    /* INT_MAX */

/* This is portable, more or less */
time_t
approx_time_t_max()
{
  struct tm tm;
  time_t t0, t1;

  tm.tm_isdst = -1;
  tm.tm_min = tm.tm_sec = 59;
  tm.tm_mday = tm.tm_hour = 23;

  fprintf (stderr, "Please be patient, this takes loooong...(hours -- 
occasionally showing the year)...");
for (tm.tm_year = 99999 - 1900; tm.tm_year <= INT_MAX; tm.tm_year++) {
  if (tm.tm_year % 49999 == 0)
    fprintf (stderr, "%d", tm.tm_year - 1900);
  else if (tm.tm_year % 2503 == 0)
    fprintf (stderr, ".");
  for (tm.tm_mon = 0; tm.tm_mon <= 11; tm.tm_mon++)
#if 0
    for (tm.tm_mday = 21; tm.tm_mday <= 31; tm.tm_mday++)
      if (tm.tm_mon == 1 && tm.tm_mday > 28)
        continue;
      else
        //for (tm.tm_hour = 20; tm.tm_hour <= 23; tm.tm_hour++)
          //for (tm.tm_min = 0; tm.tm_min <= 59; tm.tm_min++)
            //for (tm.tm_sec = 0; tm.tm_sec <= 59; tm.tm_sec++)
#endif /* commented out */
              if ((t0 = mktime (&tm)) == (time_t)(-1))
                goto out;
              else t1 = t0;
  }
out: /* NOP */ ;

  /* FIXME not portable: time_t can be a floating point type,
   * or any integer type other than long or long long.
   */
  fprintf (stderr, "time_t_max = 0x%"PRIX64"\n", t1);
  return t1;
}