1

I am using this code:

struct timeval tv;
time_t nowtime;
struct tm *nowtm;
char tmbuf[64], buf[64];

gettimeofday(&tv, NULL);
nowtime = tv.tv_sec;
nowtm = localtime(&nowtime);
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof buf, "%s.%06d", tmbuf, tv.tv_usec);

from this SO answer:

https://stackoverflow.com/a/2409054/997112

to print a struct timeval in to a readable format. However, I get this compiler warning:

warning: format '%06d' expects type 'int', but argument 5 has type '__suseconds_t'

Could somebody please help?

Community
  • 1
  • 1
user997112
  • 29,025
  • 43
  • 182
  • 361
  • 3
    Quite self explanatory: `tv_usec` member of a `tv` struct is a `__suseconds_t` type. However, this is a typedef of a long, so you can display it with printf as a long number: replace `%06d` by `%06ld` – Antoine C. Jun 30 '14 at 09:16
  • @LoveMetal well I wondered why would there be something wrong with an answer with so many upvotes. Is this because of the system I am on? – user997112 Jun 30 '14 at 09:24
  • Well... I wonder too xD. Try a little cast to `long`, it often solve a problem. – Antoine C. Jun 30 '14 at 09:28
  • 1
    @LoveMetal it worked! Put as answer and I will accept. – user997112 Jun 30 '14 at 09:51

2 Answers2

4

The compiler issues a warning because the type expected by printf - int is not the same type as the argument - long (which is what __suseconds_t is). Your code will work on many current systems, whenever int and long are the same size (either 32 or 64 bits).

As there are systems where this is not the case (e.g. int 32 bit, long 64 bits), for better portability, you should cast the value to the actual type printf expects:

snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, (long) tv.tv_usec);

As the value of tv.tv_usec is always less than a million, on a system with at least 32 bit ints, "%06d" and casting to int will also work, but I would prefer staying with long.

Incidentally, the warning points out a problem with all those typedefs that are used these days. I think a relative beginner might have had a better chance at understanding the actual problem if the message had mentioned long instead of or in addition to __suseconds_t. The clang compiler actually does this: "'__suseconds_t' (aka 'long')".

Chris
  • 4,133
  • 30
  • 38
1

The tv_usec member of struct tv structure is a __suseconds_t datatype, which is a typedef to long. You can display it with %06ld instead of %06d.

And it seems like a cast to long would be better, at least for portability issues.

Antoine C.
  • 3,730
  • 5
  • 32
  • 56