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