C语言中右值到左值的强制转换



你好,我是c语言的初学者,今天我在cppreference.com上看到了一些棘手的用法示例代码

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

From my understanding:time(NULL)右值(没有名字但可以移动),如果我把上面的代码改为(time_t)(time(NULL)),这仍然是一个右值(我的编译器会给我一个错误,说你不能从这个值中获得地址)。如果我改变代码的使用(time_t){time(NULL)}这一次编译器将不会恐慌任何(现在它是一个左值) .

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

和其他一些人在他们的c++编译器上做了一个测试(请解释):

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

问题:

表示(cast_type){rvalue}这最终将是左值

这在C语言中是一个常见的用法吗?

C和c++在语义上有区别吗?

在C语言中,(time_t){ time(NULL) }是一个复合字面值C99,由time的返回值初始化。从链接的文档

复合字面值的值类别为左值(可以取其地址)。

虽然复合字面值的语法类似于强制转换,但重要的区别在于强制转换是一个非左值表达式,而复合字面值是一个左值表达式。

一些c++编译器支持复合字面值作为扩展。例如,GCC在§6.28 Compound Literals中详细介绍了一个扩展,但请注意以下区别:

在C语言中,复合字面值表示具有静态或自动存储持续时间的未命名对象。在c++中,复合字面值指定一个临时对象,该对象只存在于其完整表达式结束之前。


(time_t)(time(NULL))是将time的返回值显式强制转换为类型time_t的冗余强制转换。它是一个非左值

感谢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

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

最新更新