2017-05-31 98 views
22

的说法,我在一些源代码发现行:花括号的功能

if(pthread_create((pthread_t[]){}, 0, start_thread, pthread_args)) { 
... 

它工作正常,但如何理解第一个参数? 看来,大括号转换为pthread_t[]类型。

P.s.我GOOGLE了,但没有找到答案,只有一些猜测(某种形式的初始化,或c的遗留功能)

+13

这是一个[*复合文字*](http://en.cppreference.com/w/c/language/compound_literal)。 –

+0

@Someprogrammerdude谢谢!就是这样,我想。 – ltWolfik

回答

19

这是compound literal,具有约束冲突,因为initializer braces cannot be empty

(pthread_t[]){} 

使用gcc -std=c99 -Wall -Wextra -Wpedantic这将产生警告:

compound_literal_pthread.c:6:36: warning: ISO C forbids empty initializer braces [-Wpedantic] 
    pthread_t *ptr = (pthread_t []){}; 

结果似乎是一个指针pthread_t,虽然我不看不到gcc手册中记录的这种行为。请注意,在C++中允许使用空括号作为初始值设定项,它们相当于{ 0 }。这种行为似乎被C支持,但未被gcc支持。我怀疑这就是发生在这里,让上面的表达式等价于:

(pthread_t[]){ 0 } 

在我的系统,pthread_tunsigned long一个typedef,所以这个表达式将创建pthread_t仅包含0元素的数组。该数组将在函数调用中衰减到指向pthread_t的指针。

+5

作为一个变形的副作用,线程不可连接,因为代码不能以可访问的方式保存'pthread_t'。实际上,线程是分离的,没有正式分离的好处。作为创建线程的一种方式,它留下了许多不足之处。 –

+0

@ JonathanLeffler--很好的音符。 –

+0

我认为* C中的每个类型都可以用'{0}'正确初始化,但我不清楚为什么不允许使用空括号:假设允许初始化对象的任何单个元素为隐式,为什么不一次为他们做到这一点? (对于很多类型,{0}'在技术上可能是允许的,但在清晰的读取意义上不是“正确的”) – Leushenko

0

您正在创建一个数组与pthread[]。如果为参数定义长度,则可以在花括号中传递值。

0

你正在处理的是一个数组初始值设定项,它恰好是空数组。通常你会发现它是:

int my_array[] = (int[]){10, 20, 30}; 

而且,它还将初始化my_array包含三个要素。这里没有元素,因此语法尴尬。

+2

是一个空的大括号包含的列表被认为是一个有效的语法? AFAIR,它必须包含至少一个元素。 –

+0

是的,这是一个有效的语法。在这种情况下,你不需要写大括号,但你可以。 –

+3

@ JohannesMols--它不是有效的语法,对初始值设定项使用空括号是违反约束的。 –

1

这是一个compound literal正如@ some-programmer-dude所提到的。

在这个特定的情况下,它是用来创建一个数组来存储thread_id并稍后释放它,而不需要创建额外的变量。这是必要的,因为pthread_create不接受NULL作为thread_id的参数。