Reputation: 1023
I'm brand new at C and am still trying to understand how it works, any help is appreciated. I'm working through a code example that prints out the current local time on the user's screen. I've commented the code to help me understand what is happening and have questions about how it works;
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
//define timeval as data type time_t
time_t timeval;
//Apply the time function, found in time.h, and use timeval as parameter
(void)time(&timeval);
//Use ctime, found in time.h, and use timeval as parameter
printf("The date is: %s", ctime(&timeval));
exit(0);
}
First, I'm not clear on how exactly (void)time(&timeval)
works, especially since removing (void) doesn't seem to break how the program. From reading, my understanding is that void is used when the function returns nothing, but why is this important? Not sure why it's being used. Also, timeval's data type is declared as time_t at the beginning of the program, but what is the time function doing with it that can be made useable later on when the ctime function is using it.
Upvotes: 0
Views: 525
Reputation: 25908
Functions which return a value typically do so for a purpose. In this case time()
returns a representation of the current time on success, but also returns -1
if, for some reason, it could not get the current time.
Your code does not check this return value, and to be robust, it should, since if the call to time()
failed, then you need to be changing your plan of trying to pass the failed result to ctime()
.
Some static analysis tools, notably lint
or its modern counterpart, splint, will (or can be told to) flag an issue when you call a function which has a return value which you do not use, precisely for this reason - because the function is giving you potentially useful information which you are ignoring.
Semantically, casting the return value to (void)
is a way of stating, in code, that you are explicitly discarding that value. This arguably has some merit in itself, at the expense of cluttering up the code, but in particular it can be used to silence some of those warnings, because you're telling the analysis tool that you're doing it deliberately, and hence it need not warn you.
In this particular case, time()
also stores the value it returns in the variable pointed to be its argument, so you have two different ways to get it. Casting the return to (void)
here could be a way of saying "I'm deliberately getting the output of time()
via its argument, and I'm explicitly discarding the return value because I only need that output once and I already have it." It doesn't actually change what the code does, but it's a way of you making clear in your code what you're doing. If you're in the habit of getting the output from time()
via its return value, and for some reason in this particular case you are choosing to get it via the parameter, it's possible that adding the cast might help you later remember what you did, in case your first instinct would be to wonder why you're calling time()
and apparently not storing the result.
Whichever way you get it, though, you should still be checking for failure. For instance, although you could do something like:
time_t timeval;
time(&timeval);
if ( timeval == -1 ) {
fprintf(stderr, "couldn't get time");
return EXIT_FAILURE;
}
printf("The date is: %s", ctime(&timeval));
it would probably be more natural to do:
time_t timeval;
if ( time(&timeval) == -1 ) {
fprintf(stderr, "couldn't get time");
return EXIT_FAILURE;
}
printf("The date is: %s", ctime(&timeval));
and that's where knowing you're not using the return value may be helpful, even though you're getting the result via the argument.
The drawback is that there are some functions which do return a value which is not typically useful to check, printf()
being the obvious example. If you use a lot of these functions, your code gets quickly cluttered up with unhelpful (void)
casts, and this technique tends to become more of a distraction than a benefit, despite the good intentions.
Upvotes: 3
Reputation: 2995
Casting to (void)
is not necessary if you are not using the return value. Maybe some odd compilers out there will complain if you don't cast (e.g "return value not used"), but I doubt it. Usually, if you meant to use the return value, it will indirectly show up as an uninitialized variable warning.
When you pass timeval
by reference to the time
function, it gets set to the current system time. This is equivalent to doing timeval = time(NULL)
.
Behavior of time
:
The function returns this value, and if the argument is not a null pointer, it also sets this value to the object pointed by timer.
This is then passed to ctime
to convert it to a string to be printed.
Upvotes: 2