Graphics Programs Reference
In-Depth Information
of
current_time
, an empty
tm
struct. The address-of operator is used to provide
a pointer to
seconds_since_epoch
for the other argument to
localtime_r()
, which
fills the elements of the
tm
struct. The elements of structs can be accessed in
three different ways; the first two are the proper ways to access struct elements,
and the third is a hacked solution. If a struct variable is used, its elements can
be accessed by adding the elements' names to the end of the variable name
with a period. Therefore,
current_time.tm_hour
will access just the
tm_hour
element of the
tm
struct called
current_time
. Pointers to structs are often used,
since it is much more efficient to pass a four-byte pointer than an entire data
structure. Struct pointers are so common that C has a built-in method to
access struct elements from a struct pointer without needing to dereference
the pointer. When using a struct pointer like
time_ptr
, struct elements can be
similarly accessed by the struct element's name, but using a series of charac-
ters that looks like an arrow pointing right. Therefore,
time_ptr->tm_min
will
access the
tm_min
element of the
tm
struct that is pointed to by
time_ptr
. The
seconds could be accessed via either of these proper methods, using the
tm_sec
element or the
tm
struct, but a third method is used. Can you figure
out how this third method works?
reader@hacking:~/booksrc $ gcc time_example.c
reader@hacking:~/booksrc $ ./a.out
time() - seconds since epoch: 1189311588
Current time is: 04:19:48
reader@hacking:~/booksrc $ ./a.out
time() - seconds since epoch: 1189311600
Current time is: 04:20:00
reader@hacking:~/booksrc $
The program works as expected, but how are the seconds being accessed
in the
tm
struct? Remember that in the end, it's all just memory. Since
tm_sec
is
defined at the beginning of the
tm
struct, that integer value is also found at
the beginning. In the line
second = *((int *) time_ptr)
, the variable
time_ptr
is typecast from a
tm
struct pointer to an integer pointer. Then this typecast
pointer is dereferenced, returning the data at the pointer's address. Since
the address to the
tm
struct also points to the first element of this struct, this
will retrieve the integer value for
tm_sec
in the struct. The following addition
to the time_example.c code (time_example2.c) also dumps the bytes of the
current_time
. This shows that the elements of
tm
struct are right next to each
other in memory. The elements further down in the struct can also be directly
accessed with pointers by simply adding to the address of the pointer.
time_example2.c
#include <stdio.h>
#include <time.h>
void dump_time_struct_bytes(struct tm *time_ptr, int size) {
int i;
unsigned char *raw_ptr;