12

How can I reinitialize a timeval struct from time.h?

I recognize that I can reset both of the members of the struct to zero, but is there some other method I am overlooking?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
BSchlinker
  • 3,401
  • 11
  • 51
  • 82
  • 2
    Reinitialize it to what? How about making a copy of it after it is satisfactorily initialized, and then copying that back over the original to reset it? – wallyk Jun 24 '11 at 00:34

5 Answers5

17

The completely correct and portable (albeit C99) way to zero-initialize arbitrary (possibly aggregate) types:

myTime = (struct timeval){0};

This works even for structures that contain pointers and floating point members, even if the implementation does not use all-zero-bits as the representations for null pointers and floating point zeros.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • You beat me by two minutes :-). By the way, I think using empty braces is better in general because they work even if the first element of the struct is another struct. – Nemo Jun 24 '11 at 01:15
  • 1
    Empty braces do not work at all; they're invalid C. They are valid, however in C++. Note that `{0}` *always* works in C, even if the first element is another struct (or even if there are no structs or unions involved at all). – R.. GitHub STOP HELPING ICE Jun 24 '11 at 01:38
  • I'll buy that the empty braces are not standard; I stand corrected. However, if the first element of the struct is another struct, "gcc std=c99 -pedantic -Wall" says "warning: missing braces around initializer". It wants myStruct = (struct mystruct){ { 0 } }. Is this a pointless warning? – Nemo Jun 24 '11 at 02:03
  • 1
    @Nemo: I believe it to be a pointless and irritating warning. I could maybe see it being useful for initializers that are more than `{0}`, but GCC shouldn't warn for that specific form which is idiomatic for "I want this structure zero-initialzed". – Michael Burr Jun 24 '11 at 02:22
  • @Michael: Thanks. Yeah, that warning, plus the (non-standard) empty braces eliciting no warning, had me convinced that exactly the wrong thing was actually standard. Live and learn. – Nemo Jun 24 '11 at 02:24
  • Indeed, I agree with Michael 100%, both that the warning in its current form is annoying and harmful, and that the correct fix would be to special-case `{0}` as "never warn" while still issuing the warning for any non-zero initializer without the "correct" number/levels of braces. – R.. GitHub STOP HELPING ICE Jun 24 '11 at 02:24
  • 2
    @R. @Michael, yes that warning is really annoying. I usually switch that particular one off. I even think that in general that warning is really misleading. The standard has an explicit paragraph on how this "flattened" initializers work. This a feature that is wanted by the language (designers). The warning only has the effect that only few people use initializers at all. It is just counterproductive. – Jens Gustedt Jun 24 '11 at 06:36
5

memset may happen to work on your platform, but it is actually not the recommended (portable) approach...

This is:

struct timeval myTime;

myTime = (struct timeval){ 0 };

memset works because all of the elements of struct timeval happen to have zero values that are represented by the all-zeroes bit pattern on your platform.

But this is not required by the spec. In particular, POSIX does not require the time_t type to be an integer, and C does not require floating-point zero to be represented as all-zero bytes.

Using the initializer syntax guarantees the fields of the structure will be properly set to zero, whether they are integral, floating point, pointers, or other structures... Even if the representation of those things is not all-zero in memory. The same is not true for memset in general.

Nemo
  • 70,042
  • 10
  • 116
  • 153
1

Assuming that you want a struct timeval structure reinitialized to zero values regardless of whether they're floating point types or integral types and regardless of the zero representation for floating point types, a method that will work with C90 or later or C++:

static struct timeval init_timeval;  // or whatever you want to call it

// ...

myTime = init_timeval;

As in R.'s answer and Nemo's answer, this will also handle NULL pointers regardless of how they might be represented. I can't imagine why a struct timeval would have a pointer, but I mention this because the technique is useful for structures other than struct timeval.

The drawback to it in comparison with the other answers is that it requires a static or global variable to be defined somewhere. The advantage is that it'll work with non-C99 compilers.

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • If you're going to do this, at least add `const` to avoid wasting bss/data. Also, if you write `const struct timeval init_timeval = {0};` (notice I removed `static`) the compiler **might** be smart enough to eliminate generating any code to actually create the automatic object and just generate the `memset`-equivalent code when you write `my_timeval = init_timeval;`... – R.. GitHub STOP HELPING ICE Jun 24 '11 at 02:27
0

If you're looking for a one-liner, I guess you could also use memset to to the job :

struct timeval myTime;

/* snip ... myTime is now initialized to something */

memset(&myTime, 0, sizeof(timeval)); // Reinitialized to zero
Fred
  • 4,894
  • 1
  • 31
  • 48
  • 1
    Do NOT retag questions from `c++` to `c` just because OOP isn't involved. Now all the answers don't actually work in the OP's C++ code. – Ben Voigt Jun 30 '11 at 23:13
-2

You could use memset, then you'd also zero any platform-specific members.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720