简体   繁体   中英

Casting rvalue to lvalue in C programming language

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++?

In C, (time_t){ time(NULL) } is a compound literal C99 , 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 .

Thanks for the answer provided by Oka .

My question now is cleared.

This kind of usage is called compound literals 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 is 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM