Home > front end >  Casting rvalue to lvalue in C programming language
Casting rvalue to lvalue in C programming language

Time:05-28

Hello I am a beginner learner in c , today I saw some tricky usage example code in cppreference.com

struct tm tm = *localtime(&(time_t){time(NULL)});

From my understanding : time(NULL) is a rvalue ( no name but movable ), and if i change the code above to (time_t)(time(NULL)) , this will still be a rvalue( my compiler will give me an error says that you cannot get an address from this value ). And if i change the code to their usage (time_t){time(NULL)} this time the compiler will not panic anything( now it's a lvalue).

Some people says the above code temporarily defined a structure in type (time_t) ( Are they correct ?) .

and some other people did a test on their C compiler ( please explain ) :

says (time_t){time(NULL)} this will still be a rvalue which is opposite to the C programming language .

Questions:

Is that indicates (cast_type){rvalue} this will eventually be a lvalue in C ?

Is this a common usage in C?

Is it a sematic difference between C and C ?

Please critisize , thank you.

CodePudding user response:

In C, (time_t){ time(NULL) } is a compound literalC99, initialized by the return value of time. From the linked documentation

The value category of a compound literal is lvalue (its address can be taken).

Although the syntax of a compound literal is similar to a cast, the important distinction is that a cast is a non-lvalue expression while a compound literal is an lvalue.

Some C compilers support compound literals as an extension. For example, GCC details an extension in §6.28 Compound Literals, but note this difference:

In C, a compound literal designates an unnamed object with static or automatic storage duration. In C , a compound literal designates a temporary object that only lives until the end of its full-expression.


(time_t)(time(NULL)) is a redundant, explicit cast of the return value of time to the type time_t. It is a non-lvalue.

CodePudding user response:

Thanks for the answer provided by Oka.

My question now is cleared.

This kind of usage is called compound literal and it appears in C99 and later standards.

The purpose of this usage is probably when someone wants to pass an address (where it could only be obtained by a lvalue , this required by the compiler) of a function returned object ( which is a rvalue ) into another function by a pointer.

For exmaple (in our case) :

#include <time.h>
#include <stdio.h>
 
int main(void)
{
  // struct tm* localtime ( const time_t *timer);
  // time_t time ( time_t *arg);
  // char* asctime(const struct tm* time_ptr);

  time_t t = time(NULL);
  struct tm* ptm = localtime(&t);

  printf("%s", asctime(ptm));

}

If we use the compound litreal instead , the example code (which is cppreference.com provided would be:

#include <time.h>
#include <stdio.h>
 
int main(void)
{
    struct tm* ptm = localtime(&(time_t){time(NULL)});
    printf("%s", asctime(ptm));
}

Both results would be likely the following :

./main.out
Sat May 28 19:52:34 2022

And this probably would help to improve the code density and reduce the size of your program.

  • Related