在C编程语言中将右值转换为左值

Casting rvalue to lvalue in C programming language

你好,我是 c 的初学者,今天我在 cppreference.com

中看到了一些棘手的用法示例代码

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

根据我的理解time(NULL) 是一个 rvalue(没有名称,但可移动), 如果我将上面的代码更改为 (time_t)(time(NULL)) ,这仍然是一个 rvalue(我的编译器会给我一个错误,说你不能从这个值中获取地址)。如果这次我将代码更改为它们的用法 (time_t){time(NULL)} ,编译器将不会出现任何恐慌(现在它是 lvalue)。

有人说上面的代码临时定义了一个(time_t)类型的结构体(对吗?).

其他一些人对他们的 C++ 编译器进行了测试(请解释):

(time_t){time(NULL)} 这仍然是一个 rvalue 与 C 编程语言相反。

问题:

这是否表明 (cast_type){rvalue} 这最终将成为 C 中的 lvalue

这是 C 中的常见用法吗?

这是C和C++的语义区别吗?

在 C 中,(time_t){ time(NULL) } 是一个 compound literalC99, initialized by the return value of time。来自链接文档

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.

一些 C++ 编译器支持复合文字作为扩展。例如,GCC details an extension in §6.28 Compound Literals,但请注意此差异:

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))是多余的,explicit cast of the return value of time to the type time_t。这是一个non-lvalue.

感谢 Oka 提供的答案。

我的问题现在解决了。

这种用法称为复合文字,它出现在C99及以后的标准中。

这种用法的目的可能是当有人想传递一个函数的地址(它只能通过左值获得,这是编译器所要求的)通过指针将对象(右值)返回到另一个函数。

例如(在我们的例子中):

#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));

}

如果我们改用复合文字,示例代码(cppreference.com 提供的代码将是:

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

两种结果都可能如下所示:

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

这可能有助于提高代码密度并减小程序的大小。