在C++中,&(int) {1}的含义是什么?

29

我在这里看到了这个,但我不知道它的意思:

&(int) { 1 }

我认为这很奇怪,因为它看起来像是无效的语法。它将一个带有随机1的块范围进行转换(没有分号),然后取地址。对我来说没有太多意义。你们能给我解释一下吗?

我已经尝试了C++11,可以编译:

auto a = &(int) { 1 };

但是我不知道该如何处理这个变量。


这段代码的背景是什么?它本身无法编译... - yizzlez
看起来像是一个复合字面量,但没有更多的上下文无法确定,更可能是C代码,因为它在C++中作为扩展被支持,而且取其地址可能会产生不同的语义,所以这可能不是一个好主意。 - Shafik Yaghmour
@awesomeyi 我不记得了。而且在谷歌上找到的代码通常也无法编译。 - Enu Ynu Ti
2
@awesomeyi 它可以在CR的这个热门问题中找到! - Schism
@Schism 虽然这似乎是可能的,但 OP 似乎在该网站上没有账户,因此如果 OP 可以确认这确实是情况,那将会很有帮助。 - Shafik Yaghmour
2个回答

32
据我所知,这是一个复合字面量,它是C99的特性。它不是标准的C++,但gcc和clang都支持它作为扩展使用。

ISO C99 supports compound literals. A compound literal looks like a cast containing an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer; it is an lvalue. As an extension, GCC supports compound literals in C90 mode and in C++, though the semantics are somewhat different in C++.

Usually, the specified type is a structure. Assume that struct foo and structure are declared as shown:

 struct foo {int a; char b[2];} structure;

Here is an example of constructing a struct foo with a compound literal:

 structure = ((struct foo) {x + y, 'a', 0});

This is equivalent to writing the following:

 {
   struct foo temp = {x + y, 'a', 0};
   struct
在这种情况下,a 的类型将指向 int。希望最初的代码是 C 代码,因为 gcc 文档中说:

在 C 中,复合字面值指定具有静态或自动存储期的无名对象。在 C++ 中,复合字面值指定一个临时对象,该对象仅存在于其完整表达式结束之前。

因此,在 C++ 中获取地址可能不是一个好主意,因为对象的生命周期在完整表达式结束时结束。虽然它可能是依赖于未定义行为的 C++ 代码。

这是其中一种使用正确标志真正有所帮助的情况,在 gcc 和 clang 中使用 -pedantic 将产生警告和错误,例如,gcc 会说:

warning: ISO C++ forbids compound-literals [-Wpedantic]
 auto a = &(int) { 1 };
                     ^
error: taking address of temporary [-fpermissive]

如果我们在gcc中使用-fpermissive,它确实允许编译此代码。我无法使用任何标志在现代版本中使clang构建此代码,尽管旧版本似乎允许使用-Wno-address-of-temporary。我想知道gcc是否将其作为旧扩展的遗留物允许。
请注意,问题C中的神秘结构定义具有复合字面量的相当有趣(根据您对有趣的定义)。
假设Schism 是正确的并且这个问题是最初的来源,那么该代码示例中的用法:
if (setsockopt(server_connection.socket, SOL_SOCKET, SO_REUSEADDR, &(int) { 1 }, sizeof(int)) < 0) {

在C99和C++中都是有效的用法。


6

这段代码的作用并不是立即显而易见的,但如果您查看周围的代码,就会明确其使用方法和要求。

它获取一个临时匿名结构体的地址,该结构体包含一个匿名整数,该整数通过C99指定的初始化器进行初始化。原因是setsockopt不想要一个整数,而是指向它的指针(或者更准确地说,是指向某个东西的指针以及该东西的大小)。

换句话说,这是一种非常酷的技巧,可以为预期要求指针的函数提供类似于整数参数的内容(而无需显式地创建临时变量)。

因此,从功能上讲,它与以下代码完全相同:

int blah = 1;
setsockopt(..., &blah, ...);

...除了不需要引入blah之外,它可以正常工作。


我有点担心假设引用的是OP所指的那个... Schism在评论中暗示是从那里来的,但OP尚未确认。链接是由另一个用户而不是OP添加的。 - Shafik Yaghmour
@ShafikYaghmour:啊,我没有注意到那个评论不是来自原帖的人,以为是。 - Damon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接