1

Please, consider the following program:

#include <stdio.h>
#include <time.h>
#define N 10000
int main ()
{
    time_t begin1,end1;
    float diff1;
    int begin2, end2, diff2;
    int i;

    begin1 = time (NULL);
    begin2 = time (NULL);

    //consuming time
    for(i=0;i<N;i++){
        printf("%.2f%%\n",(i/(float)N)*100);
    }

    end1 = time (NULL);
    end2 = time (NULL);

    diff1 = difftime(end1, begin1);
    diff2 = end2-begin2;

    printf("%f\t%d\n",diff1, diff2);
    return 0;
}

We can see that the program works perfectly. It calculates the time differences in two ways. And both provide the same answer. I'm wondering why it is possible to implicit convert the result of calling time(NULL) to an integer variable in this way.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Zaratruta
  • 2,097
  • 2
  • 20
  • 26
  • `time_t` is probably a defined as such `typedef uint64_t time_t;` or some equivalent notation. – Jazzwave06 Nov 20 '18 at 15:15
  • @sturcotte06 I would usually see that signed, as my answer implies, but I believe we are both in the same spirit. – gsamaras Nov 20 '18 at 15:18
  • @sturcotte06 If it were unsigned you could not represent times before `1970`. – Osiris Nov 20 '18 at 15:20
  • @Osiris C could use a unsigned type starting from AD 1 and easily represent 'times before 1970". Portable code avoids assumptions, even though `time_t` very commonly uses a Jan 1, 1970 epoch,it is not required. – chux - Reinstate Monica Nov 20 '18 at 16:38
  • 1
    In support of @chux, the C standard is explicit that the encoding of the `time_t` value returned by `time()` is unspecified, and requires only that its value be the implementation's "best approximation" to the current calendar time. It requires of `time_t` only that it be a real type "capable of representing times". POSIX is much more specific, but not every C implementation conforms to POSIX. – John Bollinger Nov 20 '18 at 16:49
  • 2
    "Works perfectly" is an exaggeration - it works some of the time (when you're looking) because the time difference is small relative to `INT_MAX`, so the lost range is steady and you get away with it (and you have a platform where narrowing signed types gives a consistent result). – Toby Speight Nov 20 '18 at 17:38

2 Answers2

2

I'm wondering why it is possible to implicit convert the result of calling time(NULL) to an integer variable in this way.

No, not for portable robust code and get consistent expected results.

  1. difftime() returns a double. Saving as a float can certainly lose range and precision. It returns the difference in seconds.

    // float diff1;
    double diff1 = difftime(end1, begin1);
    
  2. time_t type is a scalar. Commonly that is some wide integer and commonly a signed integer. Yet it not need be. Saving as an int can lose range (not uncommon) and precision if time_t was some floating point type (rare). time_t is often scaled in seconds, but that is not required by C. Others units are possible.

    // int begin2 = time (NULL);
    time_t begin2 = time (NULL);
    ...
    // int end2 = time (NULL);
    time_t end2 = time (NULL);
    
    printf("%f\n",difftime(end2, begin2));
    

How the casting of time_t works in C?

Detail. OP's post does not cast anything, except go (float)N. The code does assign a time_t to an int and causes a conversion. That is similar to casting though.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • It might be useful to point out that the [POSIX.1](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html) standard does require that `time_t` is an integer type (in seconds), and that's why code that relies on POSIX.1 features often do direct arithmetic on `time_t` values. – Nominal Animal Nov 20 '18 at 19:06
0

First, check the prototype of time():

time_t time (time_t* timer);

where you can see that the return type is time_t, which generally is implemented as a long integer.

That is not standard though, which means you can't rely on this when you have to take portability into account.

Read more in What is ultimately a time_t typedef to?

gsamaras
  • 71,951
  • 46
  • 188
  • 305