你好,我是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
这可能有助于提高代码密度并减小程序的大小。